C语言的一些可能犯迷糊的基础

    技术2022-07-05  144

    1.首先C语言有多少个关键字?答案是32个,也许很少有人蛋疼的数一数。还有define是不是关键字?当然不是。 2.sizeof是什么东西?函数?但是发现 sizeof int 可以编译过去,答案不言而喻,sizeof是运算符,不是函数,当然也是关键字。 但是下面的代码: int a[100]; sizeof(a[100])的值是多少?我的编译器执行后的是4,可能会和你心目中的数不一样。 那么sizeof(a)呢?答案是400! sizeof(&a)呢?答案是4!我是被震撼了。 void fun(int a[100]) { printf("%d",sizeof(a)); } 结果是4!好吧,我已经晕了,说实话我也是不懂这究竟是什么情况。具体的需要大家自己去研究。 3.const修饰的到底是什么? const int *p; // p 可变,p 指向的对象不可变 int const *p; // p 可变,p 指向的对象不可变 int *const p; // p 不可变,p 指向的对象可变 const int *const p; //指针p 和p 指向的对象都不可变 先忽略类型名(编译器解析的时候也是忽略类型名),我们看const 离哪个近。“近水楼台先得月”,离谁近就修饰谁。注:括号括起来的部分表示忽略掉。 const (int) *p; //const 修饰*p,p 是指针,*p 是指针指向的对象,不可变(int) const *p; //const修饰*p,p 是指针,*p 是指针指向的对象,不可变(int) *const p; //const修饰p,p 不可变,p 指向的对象可变 const (int) *const p; //前一个const 修饰*p,后一个const 修饰p,指针p 和p 指向的对象 4.int i=1; int j; j=i+++i+++i++; 首先你可能会问这能编译过去吗?必须能,执行后结果是3,执行后i的值为4;首先,弄明白这个问题,i+++i是怎么运算的? 是(i++)+i呢,还是i+(++i); C 语言有这样一个规则:每一个符号应该包含尽可能多的字符。也就是说,编译器将程序分解成符号的方法是, 从左到右一个一个字符地读入,如果该字符可能组成一个符号,那么再读入下一个字符, 判断已经读入的两个字符组成的字符串是否可能是一个符号的组成部分;如果可能,继续读入下一个字符, 重复上述判断,直到读入的字符组成的字符串已不再可能组成一个有意义的符号。这个处理的策略被称为“贪心法”。 需要注意到是,除了字符串与字符常量,符号的中间不能嵌有空白(空格、制表符、换行符等)。比如:==是单个符号, 而= =是两个等号。这样应该能弄清楚了吧。上面实际上是j=(i++)+(i++)+(i++); 5.大家都知道的,定义一个变量,你要初始化它。因为变量一般在系统中占有一块内存,如果你不 初始化,而且这块内存存储有数据,也许你就要悲剧。 6小小的注意 结构体里面还可以有结构体; register 变量必须是一个单个的值,并且其长度应小于或等于整型的长度。而且register 变量可能 不存放在内存中,所以不能用取址运算符“&”来获取register 变量的地址。 关于switch:如果需要检查同一变量有两种以上的可能值,使用switch语句合适。 如果要检查的是真/假条件,则应该使用if。 7. 关于puts函数和printf函数的一点吹毛求疵 当你需要输出的不包括变量或常量,也就是你只打出一段话 如“Hello World”的时候(说的不专业 ,请见谅),适合使用puts()。虽然printf函数的功能强大,但是开销自然也大。 ps: 可以在puts()中用转义说明符比如/n,但是不能使用转换说明符 如%d 8. 外部变量,有时候叫全局变量,严格的讲外部变量的作用域应该为包含该变量定义的整个源代码文件。 实际编程中很少使用外部变量,是因为使用外部变量违背了模板独立原则,而这种原则是结构化编程的核心。 当函数使用外部变量时,在该函数内使用关键字来“声明”该变量,是个很好的编程惯例。 注意:如果你没有给外部变量初始化(也就是赋值),那么,编译器将会把它初始化为0. 局部变量,作用域为其所在的函数,注意的是编译器不会自动将局部变量初始化为0,所以,使用局部变量之前,必须明确地给它赋值。局部变量默认是动态的,意味着每次调用函数时,都要重新创建变量,而当函数执行完毕,变量将会被释放。 意味着在函数被调用两次之间,函数的动态变量就丢失。 为说明下外部变量,下面给出一段代码: #include int ctr; void print_letter2(void); char letter1 ='x'; char letter2 = '='; int main() { for(ctr=0;ctr<10;ctr++) { printf("%c",letter1); print_letter2(); } return 0; } void print_letter2(void) { for(ctr=0;ctr<2;ctr++) printf("%c",letter2); } 这是个死循环,错误使用外部变量的后果。 8.注意数据溢出现象: int main() { unsigned i; for(i=9;i>=0;i--) { printf("%u/n",i); getch(); } return 0; } i的范围是0到 2的32次方减1 数据发生溢出,造成死循环。

     

    #define AAA 1;#define BBB 2;

    int addDe() { int re =  AAA * BBB; return re;}int main(int argc, char* argv[]){ int a = addDe(); return 0;}

    竟然会提示C2100错误。百思不解,用加号+代替*就没有错误,原因何在?

    查了一下MSDN:对C2100错误的解释是,*后面是一个非指针变量。大惑,乘号怎么被看成了指针取值?后来一查,原来是一个很简单的错误,在#define的一行结束有“;”。像这种仅仅定义一个常量的的#define语句在一行结束应该是没有分号的。由于宏定义采取的源代码替换,所以到了表达式AAA * BBB;就被替换成了1;*2;;当然会报非指针变量错误啦。


    最新回复(0)