赞
踩
1.字符串反转,比如输入abcd123,然后编程321dcba
- #include<stdio.h>
- #include<string.h>
-
- int main(void)
- {
- char buf[10];
- char t;
- int len;
- puts("enter a string:");
- fgets(buf,sizeof(buf),stdin);
- puts("before:");
- puts(buf);
- len=strlen(buf);
- for(int i=0;i<len/2;i++)
- {
- t=buf[i];
- buf[i]=buf[len-1-i];
- buf[len-1-i]=t;
-
- }
- puts("after:");
- puts(buf);
-
- return 0;
- }

注意:fgets(scanf函数不能接受空格,而fgets函数可以)函数第一个参数是缓冲区buf,第二个是buf-1的大小,因为我们还有一个“\0”要占最后一个字节。字符串反转大概思路就是:第一个字符串和最后一个字符串对调,第二个字符串和最后一个字符串对调,这样依次完成,因为我们最后一个字符是结束符,所以要在for循环里面-1;
2.define宏定义
- #include<stdio.h>
- #include<string.h>
-
- #define M 5
- #define N M+M
-
-
- int main(void)
- {
- int k;
- k=N*N*5; //M+M*M+M*5 5+25+25
- printf("%12d\n",k);
-
- return 0;
- }
当时做错的原因:define N M+M ,M=5;我把M+M算出来,不能这样,是N替换M+M,只要遇到N就替换为M+M,而不是把M+M算出来为10;
3.++ i 是先加后赋值;i ++ 是先赋值后加;++i和i++都是分两步完成的
- #include<stdio.h>
- #include<string.h>
-
- int main(void)
- {
-
- int m=5;
- if(m++>5)
- printf("%d\n",m);
- else
- printf("%d\n",--m);
-
- return 0;
- }
m++>5,是先赋值,也就是先在if里面判断,然后再++;判断m没有大于5,执行else,然后--m;--是先减,然后再赋值,m在上面++过了,变成了6,在下面是--m,然后再赋值,所以结果是5。如果是是m--,那么结果就是6,先赋值,再减。
4.指针和i++
- #include<stdio.h>
- #include<string.h>
-
- int a[]={0,2,4,6,8};
-
- int main(void)
- {
- int i;
- int *p=a;
- for(i=0;i<4;i++)a[i]=*p++;
- printf("%d\n",a[2]);
-
- return 0;
- }
解释:*p++就相当于*(p++),p先与++结合,然后p++整体再与*结合。*p++解析:++先跟p结合,但是因为++后置的时候,本身含义就是先运算后加1(运算指的是整体与前面的*进行运算;加1指的是p+1),所以实际上*p++符号整体对外表现的值是*p的值,运算完成后p再加1;等同于:*p,p+=1;
(*p)++这个的意思是:先去处p里面的值赋值给人家,再把p里面的值+1;
5.
- void foo(void) {
- unsigned int a = 6;
- int b = -20;
- (a+b > 6) puts("> 6") : puts("<= 6")
- }输出的是什么
unsigned 是无符号数。 b 是有符号数负数,无符号数和有符号数混合运算 要注意 你到底 想计算什么。默认,把有符号数内容 当成无符号数解释 计算。-20 就当 0xffffffec (4294967276).显然(a+b > 6) 成立。输出 > 6。
6.三目运算符也叫条件运算符
如果希望获得两个数中最大的一个,可以使用 if 语句,例如:
if(a>b){ max = a; }else{ max = b; }
不过,C语言提供了一种更加简单的方法,叫做条件运算符,语法格式为:
表达式1 ? 表达式2 : 表达式3
运算规则是这样的:如果表达式1的值为真,则以表达式2 的值作为整个条件表达式的值,否则以表达式3的值作为整个条件表达式的值。
上面的 if else 语句等价于:
max = (a>b) ? a : b; //a>b,就输出a,否则输出b
我们来看一道面试题
#define Min(a,b) ( ((a)>=(b)) ? (b) : (a) )
7.关键字const是什么含意?
- const int a;
- int const a;
- const int *a;
- int * const a;
- int const * a const;
首先理解一下 const int *a 和int *const a,去掉int,变成 const *a, 这样理解const 修饰 *a,*a就是a所指的那个数字,就是那个数字不能被改变。这样就比较好理解int *const a,去掉int,const修饰a,a是指针(里面存的地址)也就是里面的地址不能不改变。前两个的作用是一样,a是一个常整型数。第三个意味着a是一个指向常整型数的指针(也就是,整型数是不可修改的,但指针可以)。第四个意思a是一个指向整型数的常指针(也就是说,指针指向的整型数是可以修改的,但指针是不可修改的)。最后一个意味着a是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的,同时指针也是不可修改的)。
8.指针与指针相减
我们直接来看这道题,老爱忘记。
- #include<stdio.h>
-
-
- int main(void)
- {
-
- int *p1,*p2,a[10];
- p1=a;
- p2=&a[5];
- printf("%d\n",p2-p1);
-
- return 0;
- }
解析:任何编译器上都是5。指针减法含义:两个地址之间有多少个计量单位,那么p2-p1的意思就是p2和p1之间有多少个int,那么不管in是16位,还是32位,甚至是64位,和int的长度没有关系。
9.中断问题
中断是嵌入式系统中重要的组成部分,这导致了很多编译开发商提供一种扩展—让标准C支持中断,从而产生了一个新的关键字 __interrupt。下面的代码就使用了__interrupt关键字去定义了一个中断服务子程序(ISR),请评论一下这段代码。
__interrupt double compute_area (double radius)
{
double area = PI * radius * radius;
printf("\nArea = %f", area);
return area;
}
答: a、ISR不能返回一个值。
b、ISR不能传递参数。
c、在许多处理器编译器中,浮点一般都是不可冲入的。有些处理器编译器需要让额外的寄存器入栈,有些处理器编译器就不允许在ISR中做浮点运算。此外ISR应该是短而有效率的。在ISR中做浮点运算是不明智的。
d、printf经常是有冲入性和性能上的问题,所以一般不使用printf函数
10.++前置++后置
- #include<stdio.h>
-
-
- int main(int argc, char *argv)
- {
- int a = 1, b = 1;
- int aplus, bplus;
- aplus = a++; //先把a的值赋值给aplus,a再加1
- bplus = ++b; //b的值先加1, 再把值赋值给bplus
- printf("a aplus b bplus\n");
- printf("%d %d %d %d\n", a, aplus, b , bplus);
- return 0;
- }
程序运行如下:
a aplus b bplus
2 1 2 2
- #include<stdio.h>
- #define TEN 10
-
- int main(int argc, char *argv)
- {
- int n = 0;
- while (n++ < TEN)
- printf("%5d",n);
- printf("\n");
-
- return 0;
- }
程序运行如下:
1 2 3 4 5 6 7 8 9 10
分析 :这里是先比较大小再加1, n一开始为0,0小于10,n+1,输入1,一直加到9小于10,9+1,所以输出10
- #include<stdio.h>
- #define TEN 10
-
- int main(int argc, char *argv)
- {
- int n = 0;
- while (++n < TEN)
- printf("%5d",n);
- printf("\n");
-
- return 0;
- }
程序运行如下:
1 2 3 4 5 6 7 8 9
分析:这里是先比较大小,再+1,相当于n = n+1;
11.指针偏移量的问题
- #include <stdio.h>
-
- int main()
- {
- int a[] = {1, 2, 3, 4, 5};
- int *p = (int *)(&a + 1);
- printf("%d %d \n", *(p - 1), *p - 1);
- printf("%ld %ld\n", sizeof(a), sizeof(&a));
-
- return 0;
- }
12.指针指向常量区
str1和st2的地址是不是一样的,结果是一样的为什么呢?
- #include <stdio.h>
-
- int main()
- {
- char *str1 = "hello world";
- char *str2 = "hello world";
-
- printf("%p\n", str1);
- printf("%p\n", str2);
-
- char *str3 = str2;
- str3 = "NICE";
-
- printf("%s\n", str3);
- printf("%s\n", str2);
-
- return 0;
- }

13.函数返回值一样吗?第二个会发生段错误
- #include <stdio.h>
-
- char* get_hello1();
- char* get_hello2();
- int main()
- {
- printf("%s\n",get_hello1());
- printf("%s\n",get_hello2());
-
- return 0;
- }
-
- char *get_hello1()
- {
- char *str1 = "hello";
-
- return str1;
- }
-
- char *get_hello2()
- {
- char str2[] = "hello";
-
- return str2;
- }

14.指针的偏移量
- #include<stdio.h>
-
-
- int main(int argc, char *argv[])
- {
- int a[] = {384, 385, 386};
- char *p = (char *)a;
-
- printf("%d\n", *p);
- printf("%d\n", *(p + 1));
- printf("%d\n", *(p + 4));
-
-
- return 0;
- }
简单分析一下:大概意思就是4个字节,转换成1个字节。384的二进制是1 1000 0000,只取低8位就是1000 0000,也就是-128,*(p+1)就是指针移动1个字节,也就是到1的地方,结果就是1。
运行结果如下:
-128
1
-127
15.一道很不错的题目,对于复习大小端,和内存分布,指针偏移很有帮助。
- #include<stdio.h>
- /* 小端模式 */
-
- int main(int argc, char *argv)
- {
- int a[4] = {1, 2 ,3, 4};
- int *p1 = (int *)(&a + 1);
- int *p2 = (int *)((char *)&a + 1);
- printf("0x%x, 0x%x\n", *(p1-1), *p2);
-
- return 0;
- }
先复习一下知识点,有点忘记了
a+1:就是数组首地址加上一个元素所占的地址大小,这里int是4个字节,所以加上1x4.
&a+1:代表的是加上整个数组的大小,这里数组尺寸是4,所以+1代表的是地址加上4x4.为了更好理解,画内存图来分析理解
结果是0x4和0x2000000,0x2000000有点想不明白,看了“int *类型指针变量强制转换为char *的结果”,的博客就明白了,博客地址:
(85条消息) int *类型指针变量强制转换为char *的结果_肘子君的博客-CSDN博客_int指针强制转换成char指针
假如有这么一个程序
- int a = 0x44332211;
- int *p1 = &a;
- char *p2 = (char *)&a;
- printf("*p1 = 0x%x\n",*p1);
- printf("*p2 = 0x%x\n",*p2);
结果如下图
分析:
a,p1,p2在内存中的实际效果如下(地址是假设的)
p1和p2所指向的都是变量a的地址。
不同的地方在解指针的时候。
p1在解指针时,将0x00当作是四个字节的内存空间大小的首地址。然后以int的解析类型进行解析。也就是说在解指针时会将从0x00为起始的后面总共四个地址所包含的内存空间的数都以int的解析类型解析出来。
p2在解指针时,将0x00当作是一个字节的内存空间大小的首地址。然后以char的解析类型进行解析。也就是说在解指针时会将从0x00为起始的后面总共一个地址所包含的内存空间的数都以char的解析类型解析出来。
0x44332211在变量a指向的内存空间中的分布。
*p1取a中的值时:四个字节作为整体一起解指针
*p2取a中的值时:对一个字节的空间大小进行解指针
由于p1和p2的指针类型不同。所以在对p1和p2做+1操作时,效果也会不同。
p1+1后,p1+1指向的内存地址为0x00+4=0x04;
p2+1后,p2+1指向的内存地址为0x00+1=0x01;
16.字符串大写字母转小写字母,代码比较简单,忘记的话就需要看一下ascii码
- #include<stdio.h>
- #include<string.h>
-
- int main()
- {
- int i, len;
- char s[101] = {0};
- gets(s);
- len = strlen(s);
- //大写变小写
- for(i = 0; i < len; i++) {
- if(s[i] >= 'A' && s[i] <= 'Z') {
- s[i] = s[i] + 32; /* 不明白就看一下ASCII码 */
- }
- }
- puts(s);
- return 0;
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。