被初中生 C 语言考住了,尴了个尬

2022-08-28 11:32:15 +08:00
 52coder

周末来老婆老家,她亲戚有个小孩读初中,有个兴趣班学的 C 语言,得知我是从事软件开发 5 6 年的“高手”,饭后问了我一道编程题,我三俩下就告诉他怎么 怎么写,结果提交的时候始终显示有问题,一排查发现这里有坑,我手写一个 demo (可能编译不过哈)请教各位如下程序输出是什么?

#include <stdio.h>
int main()
{
    int arr[10] = {-1};
    //打印 arr 全部内容
    for(int i = 0;i < 10;i++)
    printf("%d",arr[i]);
    
    return 0;
}

我之前一直以为会全部输出-1 ,结果在 gcc 11.2.0 的环境下,输出确实一个-1 ,然后全是 0.有没有踩过这个坑的朋友?

10181 次点击
所在节点    程序员
83 条回复
vanton
2022-08-28 14:55:41 +08:00
嗯?
这个结果不是显而易见的么。
microxiaoxiao
2022-08-28 14:57:27 +08:00
对非 char 类型的不要用 memset ,达不到想要的效果,要循环初始化。
betatabe
2022-08-28 15:42:41 +08:00
不少人 memset 都没搞清楚咋用啊
muzuiget
2022-08-28 15:49:10 +08:00
本来就是这样,这不是 C 语言的问题,是编译器的问题。

编译器看到“int arr[10]”,生成“分配 10 * 4 个字节长内存”的指令,然后再生成“把首个字节的设置为 -1 的指令”。

所以关键是分配内存这个指令问题,分配的内存可能是曾经使用过的内存地址,里面的数据可能是曾经使用过的,可以是任意数据;也很大机率是全新的未使用地址,数据全是 0 。

换句话说,刚分配内存里面都是“脏数据”,你用了脏数据,就是要后果自负。
jedihy
2022-08-28 15:52:22 +08:00
{0} 是 C compiler 的特例。所有主流 compiler 的实现都是全部赋值 0 。
betatabe
2022-08-28 15:54:43 +08:00
@muzuiget c 语言规定了就是 0 哦,前面都发了文档不看的吗
52coder
2022-08-28 16:04:16 +08:00
@microxiaoxiao
@nulIptr
@betatabe
@zhicheng
几年没写 C 代码有点脱离一线了,使用 memset 是对每个 byte 操作,针对 int 这里不适用,印象中我司代码中有一些 tricky 的方法,我网上找了个例子,可以变相达到这个目的:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h> //Use C99 standard for C language which supports bool variables

int main()
{
int i, cnt = 5;
bool *hash = NULL;
hash = malloc(cnt);

memset(hash, 1, cnt);
printf("Hello, World!\n");

for(i=0; i<cnt; i++)
printf("%d ", hash[i]);

return 0;
}
52coder
2022-08-28 16:05:38 +08:00
@betatabe 感谢指出,查了下 wiki 确实记混了,可以通过 tricky 的方法,评论里有不少朋友也存在这个误解。
ailer
2022-08-28 16:06:48 +08:00
@betatabe 有的编译器没有严格实现这个标准,脏数据是可能存在的
ailer
2022-08-28 16:09:35 +08:00
@betatabe 而且那个词是 shall ,不是强制的
betatabe
2022-08-28 16:23:08 +08:00
@ailer 在法律或规则文档中,shall 就是必须的意思
longbowape
2022-08-28 17:42:13 +08:00
@betatabe must 才是必须,shall 没有强制性,早期的编译器实现就是没有初始化的,所以都需要调用 memset
dlsflh
2022-08-28 17:57:07 +08:00
@longbowape 在需求文档或者合同或者规章中,shall 就是代表一定要完成的条目。
documentzhangx66
2022-08-28 18:10:06 +08:00
类似的还有 b = ++a ; c = a++;

我以前遇到有人问这种问题,我的建议是自动离职,别害团队了。这类东西除了在上学期间,应付奇葩的老师之外,没有半点益处,甚至还是团队毒瘤。

楼主,他问你这种问题,你应该教他正确的写法是:

int arr[10] = { -1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 };
gamesover
2022-08-28 18:52:06 +08:00
十几年前读书的时候,这就是 c 语言必考题
如果没有初始化,c 会自动帮你初始化为 0
fyxtc
2022-08-28 19:26:04 +08:00
不是坑,{0}也没有误导性,你这典型属于读死书,只记其然而没有知所以然,再说大一学 c 的时候 0 作为数组默认初始化值应该是非常深刻才对
icyalala
2022-08-28 19:47:13 +08:00
@longbowape http://port70.net/~nsz/c/c99/n1256.html#4p1
''shall'' is to be interpreted as a requirement on an implementation or on a program
phiysng
2022-08-28 19:50:05 +08:00
这不算坑,预期行为很明确的,楼主这是太长时间不用 C/C++了。
phiysng
2022-08-28 19:56:40 +08:00
```c++
void Foo() {
vector<int> vec(10,-1); // 初始化数组,值为 10 个-1
for (auto& v : vec) {
cout << v << endl;
}
}
```
C++的 vector 容器有楼主想要的这个行为。
littlewing
2022-08-28 20:31:57 +08:00
讨论这种东西没意义

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/875942

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX