读书人

C新手问个很白痴的有关问题关于数组

发布时间: 2013-07-16 22:38:05 作者: rapoo

C新手问个很白痴的问题,关于数组和指针的问题
我有个字符数组char arr[128];
我要把它作为参数传递给一个函数,函数参数申明是
void foo(char arr[])这样呢?
还是void foo(char *arr)这样?
为什么我发现两个好像都行?而且效果还一样?
然后调用应该一般只有这一种吧比如foo(arr);

然后一个问题是以上两种参数申明,不管对不对,效果貌似都是直接传地址,于是在函数内部修改数组会反映到实际的数组上,但是C中有没有传递数组时不直接传地址,而是像某些语言一样相当于复制了一个副本然后给函数参数的,也就是函数内修改数组,不会影响原来那个数组的值的?
还是说如果要实现我上面说的效果,必须自己手动复制到另外一个数组里面的。

最后一个问题(不好意思问题这么多),
int main(int argc,char *argv[])
这是主函数,还是上面那个char arr[128];
为什么arr = argv[0];这种方法不行啊。。提示说不匹配。
如果这种方法不对,那怎么才能把argv[0]的值赋值给字符数组啊。
我后来写了个char *arr;
然后arr = argv[0];貌似可以了
但是这样当要用scanf输入的时候怎么又不行了scanf("%s",arr);报错。。

本人纯C新手,下学期大一,暑假想先看看C,就搞了本C Prime Plus看,看得我云里雾里的,书感觉确实不错,不过不知道是我书没看仔细呢还是怎么滴,书上代码一敲,编译通过,一看感觉也都明白,但是自己一写就各种问题。。 C 指针 数组
[解决办法]
先回答第一个问题
1.void foo(char arr[])和void foo(char *arr)效果是一样的,当用第一种传递方式的时候,形参char arr[]的arr自动退化为指针。传递数组都是传递的数组的地址。
第二个问题
2.char arr[128]定义的是一个字符数组,char *argv[]是指针数组,代表数组里面每一个都是指针。你是不可以直接这样赋值的arr = argv[0].必须要这样赋值strcpy(arr, argv[0]),当然要确保定义的数组空间足够大,避免造成溢出。然而当你把arr定义成指针时, char *arr = argv[0]是没有问题的,这是指针之间的赋值。
标准输入的话得这样 scanf("%s", &arr)
[解决办法]
1. 正确, 两个都行, 效果一样.
2. 没有.
3. 数组名除了传参数的时候会退化成指针外, 其余时候和指针并不相同. 数组是不能直接赋值的, 只能对数组的元素一个一个赋值. 要用 arr 来保存 argv[0], 需要用 strcpy 函数来拷贝才行.
scanf 的时候需要已经分配了内存的指针, char *arr 的话必须先分配, arr = malloc(size); 才行.
[解决办法]
以数组作函数参数时,实际上传递的都是指针,这是为了避免对数组进行拷贝带来很大的开销。
[解决办法]
都对
[解决办法]
第一个问题:两种函数参数是一样的,两种都是指向字符串。函数调用字符数组,传递数组参数的时候,也是传递字符串的首地址,也就是字符数组名或者字符串指针。因为两者都是字符串的首地址。比如用printf输出字符串的时候printf("%s\n", arr); 就是只给个字符串的首地址。因为C语言中,没有专门的字符串数据类型,系统就在字符串的后面加了个'\0' 当读取字符串时,是根据字符串的首地址读到'\0',就表示字符串读完了。
第二个问题:用一个现实的例子说:宋丹丹家冰箱装大象超载坏了,她自己又从商店买了一个新的换走了旧的,不过她还可以打电话给家电商说,我家冰箱坏了,给我送台新的,我家地址是*** 。也把冰箱坏了。两种都是通过地址更换的。一个是由拥有者直接换掉的,另一个是通过地址传递换的。C语言里的指针就是这么现实的。


第三个问题:首先要清楚,数组名是不能被赋值的,arr已经是一个字符串的首地址了,不能再去改变它。char *arr ,是你定义的字符串指针。 字符数组名和字符指针的最大区别就是 数组名不能再赋值,而字符指针可以再赋值,因为字符串指针是个变量。 main函数了里面char *argv[] 中的argv是个字符串指针数组,数组里存放的是字符串指针。所以它的每个元素相当于一个字符串。char *arr; arr = argv[0],就是给字符串指针赋值,这样是对的。
[解决办法]
1
2种传参的方式是等价的.
C语言中只有将数组作为参数时char arr[]等价于char *arr;
特别是在一个文件中声明了一全局数组char arr[10],
在另一个文件里extern时一定要写成extern char arr[];决不能写成extern char *arr.

2
①数组名是指针常量,是不可以作为左值的,既不可以被赋值.
②char *argv[] 是什么?
argv是一个数组,数组内的元素都是char*,所以argv是一个指针数组,
同时,因为第1个问题的原因char *argv[] 等价于char **argv

3补充一句
char *argv[]是指针数组,指向的字符串是从命令行运行程序所加的参数,
例如[Linux]./a.out parm1 parm2 ....
那么argv[0]指向"a.out"
那么argv[1]指向"parm1 "
那么argv[2]指向"parm2 "
...类推
windows下类似[windows]C:\test.exe out parm1 parm2 ....
那么argv[0]指向"test.exe"
那么argv[1]指向"parm1 "
那么argv[2]指向"parm2 "
...类推
[解决办法]


arr == &arr[0];//数组名的值是数组第一个元素的地址
*arr = *(&arr[0]) = arr[0];//同上
arr[0] == *(arr + 0) == *(0 + arr) == 0[arr];//arr[n]只是*(arr+n)的简写


引用:
Quote: 引用:

1. 正确, 两个都行, 效果一样.
2. 没有.
3. 数组名除了传参数的时候会退化成指针外, 其余时候和指针并不相同. 数组是不能直接赋值的, 只能对数组的元素一个一个赋值. 要用 arr 来保存 argv[0], 需要用 strcpy 函数来拷贝才行.
scanf 的时候需要已经分配了内存的指针, char *arr 的话必须先分配, arr = malloc(size); 才行.

引用:
以数组作函数参数时,实际上传递的都是指针,这是为了避免对数组进行拷贝带来很大的开销。

感谢各位的解答!!!刚才忘记说了还有一个问题,
我上面说调用函数时一般只有foo(arr)这一种,但是foo(&arr[0])貌似也行?
变量申明是char arr[128];
函数是foo(char *arr)
变量名退化为指针后应该就是指向第一个元素的地址吧,所以arr和&arr[0]等效?
然后*arr和arr[0]等效?*(arr+1)和arr[1]等效?

读书人网 >C语言

热点推荐