C语言const

C语言const用法

const是一个C语言的关键字,它限定一个变量不允许被改变,产生静态作用.
常类型是指使用类型修饰符const说明的类型,常类型的变量的值是不能改变的.(可以采取别的方式修改值)

下面的代码错在哪里?

1
2
const int n = 5;
int a[n];

为什么编译器会报错,”常量”和”只读变量”是有区别的.常量,例如5,”abc”等等,肯定是只读的,常量被编译器放在只读区域,当然也就不能修改.而”只读变量”则是在内存中开辟一个地方来存放它的值,只不过这个值被编译器限定不允许修改.

下面的代码哪一句有错误?

1
2
3
4
5
6
typedef char *pStr;
char string[4] = "bbc";
const char *p1 = "str";
const char p2 = "str";
p1++;
p2++;

答案是p2++错误. const的基本使用形式: const type m; 限定m不可变,只读. 可以对应*p1不可变,p1可变.p2不可变

C语言数组名

C语言数组名

  • a&a的本质
  • 从二维数组角度分析
  • 从指针运算角度分析

a&a的本质

C语言数组名是一个特殊的东西

int a[5] = {1, 2, 3, 4, 5}

a &a &a[0]这三个的相等的

a是数组名,值是数组首元素的地址.数组名是一个指针常量,能用于指针运算
但是有两种情况比较特殊:

  • 使用sizeof操作符,结果为整个数组的长度
  • 使用&取地址操作时,得到一个数组指针

&a这才是一个数组指针,值是数组的地址

注意: &aa值相等,但是*&a*a的值不相等.说明*&a是对这个数组指针进行了取值操作,取得的是数组首元素的地址,还是一个指针,而不是对&a的值所代表的内存地址进行取值.这应该是C语言对数组指针运算的特殊规定.*a就不言而喻是数组首元素的值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
int main(int argc, const char * argv[])
{
int a[5]={1,2,3,4,5};
printf("a = %x\n",a); //数组名 值相等而已
printf("&a = %x\n",&a); //数组地址
printf("sizeof a = %d\n", sizeof(a)); //数组长度
printf("*(int*)&a = %x\n",(*((int *)(&a)))); //取得数组第一个元素的值
printf("*&a = %x\n", *(&a)); // 还是一个指针,值为数组首元素的地址
printf("**&a = %x\n",(*(*(&a)))); //数组第一个元素的值
printf("&a[0] = %x\n",&a[0]); //数组第一个元素的地址
printf("*&a[0] = %x\n",*(&a[0])); //数组第一个元素的值
printf("*a = %x", *a); //数组第一哥元素的值
return 0;
}

结果:

1
2
3
4
5
6
7
8
9
a = 5fbff780
&a = 5fbff780
sizeof a = 20
*(int*)&a = 1
*&a = 5fbff780
**&a = 1
&a[0] = 5fbff780
*&a[0] = 1
*a = 1

C语言变态的HelloWorld

C语言变态的HelloWorld

C语言真是世界上最难的语言,所以C++是最恐怖的语言

第一种实现方式,使用宏定义

1
2
3
4
5
6
7
8
9
10
11
12
// file main.c
#define _________ }
#define ________ putchar
#define _______ main
#define _(a) ________(a);
#define ______ _______(){
#define __ ______ _(0x48)_(0x65)_(0x6C)_(0x6C)
#define ___ _(0x6F)_(0x2C)_(0x20)_(0x77)_(0x6F)
#define ____ _(0x72)_(0x6C)_(0x64)_(0x21)
#define _____ __ ___ ____ _________
#include <stdio.h>
_____

看一下该代码经过预处理之后是什么样子,使用$ gcc -E main.c -o main.i

1
2
// file main.i 看最后的部分,main函数
main(){ putchar(0x48);putchar(0x65);putchar(0x6C);putchar(0x6C); putchar(0x6F);putchar(0x2C);putchar(0x20);putchar(0x77);putchar(0x6F); putchar(0x72);putchar(0x6C);putchar(0x64);putchar(0x21); }

现在我们来解析这段代码,一步一步看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdio.h>  //这句之前的都是宏定义,之后的代码在预编译阶段会进行宏替换
_____
>>>> __ ___ ____ _________
-- 先看来第一个 __
>>>> ______ _(0x48)_(0x65)_(0x6C)_(0x6C)
>>>> _______(){ _(0x48)_(0x65)_(0x6C)_(0x6C)
>>>> main(){ putchar(0x48);putchar(0x65);putchar(0x6C);putchar(0x6C);
-- 继续 ___
>>>> _(0x6F)_(0x2C)_(0x20)_(0x77)_(0x6F)
>>>> putchar(0x6F);putchar(0x2C);putchar(0x20);putchar(0x77);putchar(0x6F);
-- 继续 ____
>>>> _(0x72)_(0x6C)_(0x64)_(0x21)
>>>> putchar(0x72);putchar(0x6C);putchar(0x64);putchar(0x21);
-- 最后 _________
>>>> }

由四部分组成,所以得到了上面的那段代码
0x全是16进制数,以ASCII码形式转换成字符,前面是零,不是'鸥'
0x48 > 72 == H
0x65 > 101 == e
0x6c > 108 == l
0x6f > 111 == o
0x2c > 44 == ,
0x20 > 32 == Space(空格)
0x77 > 119 == w
0x72 > 114 == r
0x64 > 100 == d
0x21 > 33 == !

输出结果Hello, world!,你的呢?测试了吗?
此乃没有写返回值类型的main函数噢
好了,就分析这一个,剩下的贴代码,太丧心病狂了

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×