C 语言小困惑

本文最后更新于:1 个月前

C 语言小困惑

一维数组的首地址只能用数组名表示?

以上描述错误,一维数组的首地址除数组名可有其它表示

1
char c[5]={};
1. 数值名c是一个地址常量,表示数组首元素的地址

  1. &c[0]也表示数组首元素的地址

  2. &c表示的是整个数组的首地址

这三者的地址值是相同的,但第3与1、2含义却不一样,1与2不管是地址值还是含义都是一样的。 下面给出程序验证:

1
2
3
4
5
6
7
8
9
# include <stdio.h>

int main(int argc,const char *argv[])
{
char c[5];
printf("c=%p,&c[0]=%p,&c=%p\n\r",c,&c[0],&c);
printf("c+1=%p,&c[0]+1=%p,&c+1=%p\n\r",c+1,&c[0]+1,&c+1);
return 0;
}
输出结果:
1
2
c=0x7ffdd944f223, &c[0]=0x7ffd944f223, &c=0x7ffd944f223
c+1=0×7ffdd944f224,&C[0]+1=0x7ffdd944f224,&c+1=0x7ffdd944f228

可以看到,c+1&c[0]+1是以一个char型大小为单位增加的,而&c+1是以整个数组大小为单位增加的。


假设str1str2为字符串变量,将str2字符串的值赋给str1可采用str1=str2?

以上描述错误,首先,C语言没有像C++Javapython等面向对象的语言中string这样的字符串类型,C语言中的字符串是存放在字符型数组中的,字符串规定不能整体引用,只能单个引用.

赋值除了按字符串输入赋给字符数组,或者初始化为字符串外,一般只能单个元素赋值. 因为数组名是一个地址常量,不允许改变,但是数组中的元素是变量,可以改变赋值.数组名这个地址[常量]就是元素[变量]的存放位置(a[]是一个常量,但是a[0]是一个变量)

C语言中,常见的3种字符串赋值有如下:

1、通过字符数组直接初始化

1
2
3
4
5
6
7
int main()
{
char str[10] = "China";//还可以写成char str[10] ;str[10] = "China";
printf("str = %s", &str);
return 0;
}

但是,直接把数组元素赋值给数组名(也就是数组首元素的地址),是不行的
1
2
3
4
5
6
7
8
int main()
{
char str[10] ;
str = "China";
printf("str = %s", str);
return 0;
}

这样会出现编译错误:C2106(运算符的左操作数必须为左值)

2、使用strcpy函数进行初始化

1
2
3
4
5
6
7
8
int main()
{
char str1[10],str2[] = "China";
strcpy(str1, str2);//此行代码还可以写为 strcpy(str1,"China");
printf("str1 = %s", str1);
return 0;
}

这里需要注意的是,使用strcpy函数,strcpy(str1,str2),字符数组1必须定义的足够大,以便容纳被复制的字符串2,避免数组越界。

以下写法是错误的

1
2
3
char str1[10],str2 = "China";
str1 = str2;

注:

在C语言中,将一个字符串赋值给另一个字符串,只能使用strcpy函数

但是,可以使用赋值号实现对单个字符的赋值

如:

1
2
3
4
5
char str1[10];;
str1[0] = 'A';
str1[1] = 'B';
str1[2] = '\0';

这里需要注意的是,结束后一定要自行添加 ‘\0’, 否则,就会出现” AB烫烫烫烫烫烫烫 ]D痨“的编译结果

3、通过指针赋值

通过指针赋值字符串相对比较难理解,大家先看一段代码

1
2
3
4
5
6
7
8
9
#define _CRT_SECURE_NO_WARNINGS//在VS2019下可以加,否则会出现C4996问题
#include <stdio.h>
int main()
{
char* string = "I Love China";
printf("string = %s", string);
return 0;
}

如何理解这段代码:

①程序定义了一个char *类型的指针变量(字符指针变量)string,在C语言中,指针 = 地址,顾名思义,指针变量存放着地址

②字符串常量"I Love China",C语言在处理字符串常量是按字符数组来处理的。

③结合上两点可以知道,该字符指针存放的是字符常量第一个元素的地址 因此,输出时,只需告诉编译器字符常量首元素的地址即可

1
2
char* string = "I Love China";

还可以写为:
1
2
3
char * string;
string = "I Love China";//不可以写为*string = "I Love China";

不可以写为:
1
*string = “I Love China”;

因为,字符串常量在C语言中是按字符数组来存储的,string 存储地址


C语言源程序中,凡是与宏名相同的符号都会用宏体字符串进行替换?

以上描述错误,因为字符串" "中永远不包含宏,即:如果一个字符串中,发现了一个宏,则这个宏是不会被替换的。

举例:

1
2
3
# define MY_NAME  "TuringsCat"
char *str = "MY_NAME is ";
char *name = MY_NAME;

则第一个定义的字符串char *str中的MY_NAME不会被替换成“TuringsCat”。


如果int x=20,那么表达式x/=2+x的结果等于30?

以上描述错误,/=为复合赋值运算符,常用的复合赋值运算符号有:+=-=*=/=%=,有两方面的含义,首先做数学计算,而后再赋值。 运算符两边的变量先做左边的数学运算,然后将结果赋值给左边的变量。这样的写法简化了C语言的代码,结构上看起来比较清爽,提升代码效率。 举例如下: 执行完a += 1后,a = 2; 执行完b -= a+5后,b=b-(a+5)=-5; 执行完c *= a-4后,c=c*(a-4)=-6; 执行完x/=2+x后,x=x/(2+x)=20/(2+20)!=30; 故表达式x/=2+x的结果并不等于30.

由于本人水平有限,如有理解或描述错误,还请各位批评指正. 邮箱: