作者wtchen (没有存在感的人)
看板C_and_CPP
标题十三诫增修--03:你不可以提取(dereference)不知指向何方的指标
时间Fri May 13 16:50:50 2016
增加VLA跟std::array/std::vector的部份...
===============================================================
03.
你不可以提取(dereference)不知指向何方的指标(包含 null 指标)。
错误例子:
char *pc1; /* 未给予初值,不知指向何方 */
char *pc2 = NULL; /* pc2 起始化为 null pointer */
*pc1 = 'a'; /* 将 'a' 写到不知何方,错误 */
*pc2 = 'b'; /* 将 'b' 写到「位址0」,错误 */
正确例子:
char c; /* c 的内容尚未起始化 */
char *pc1 = &c; /* pc1 指向字元变数 c */
*pc1 = 'a'; /* c 的内容变为 'a' */
/* 动态分配 10 个 char(其值未定),并将第一个char的位址赋值给 pc2 */
char *pc2 = (char *) malloc(10);
pc2[0] = 'b'; /* 动态配置来的第 0 个字元,内容变为 'b'
free(pc2);
说明:指标变数必需先指向某个可以合法操作的空间,才能进行操作。
( 使用者记得要检查 malloc 回传是否为 NULL,
碍於篇幅本文假定使用上皆合法,也有正确归还记忆体 )
错误例子:
char *name; /* name 尚未指向有效的空间 */
printf("Your name, please: ");
fgets(name,20,stdin); /* 您确定要写入的那块空间合法吗??? */
printf("Hello, %s\n", name);
正确例子:
/* 如果编译期就能决定字串的最大空间,那就不要宣告成 char* 改用 char[] */
char name[21]; /* 可读入字串最长 20 个字元,保留一格空间放 '\0' */
printf("Your name, please: ");
fgets(name,20,stdin);
printf("Hello, %s\n", name);
正确例子(2):
若是在执行时期才能决定字串的最大空间,C提供两种作法:
a. 利用 malloc() 函式来动态分配空间,用malloc宣告的阵列会被存在heap
须注意:若是宣告较大阵列,要确认malloc的回传值是否为NULL
size_t length;
printf("请输入字串的最大长度(含null字元): ");
scanf("%u", &length);
name = (char *)malloc(length);
if (name) {
// name != NULL
printf("您输入的是 %u\n", length);
} else {
// name == NULL
puts("输入值太大或系统已无足够空间");
}
/* 最後记得 free() 掉 malloc() 所分配的空间 */
free(name);
name = NULL; //(注1)
b. C99开始可使用variable-length array (VLA)
须注意:
- 因为VLA是被存放在stack里,使用前要确认array size不能太大
- 不是每个compiler都支援VLA(注2)
- C++ Standard不支援(虽然有些compiler支援)
float read_and_process(int n)
{
float vals[n];
for (int i = 0; i < n; i++)
vals[i] = read_val();
return process(vals, n);
}
正确例子(3):
C++的使用者也有两种作法:
a. std::vector (不管你的阵列大小会不会变都可用)
std::vector<int> v1;
v1.resize(10); // 重新设定vector size
b. C++11以後,若是确定阵列大小不会变,可以用std::array
须注意:一般使用下(存在stack)一样要确认array size不能太大
std::array<int, 5> a = { 1, 2, 3 }; // a[0]~a[2] = 1,2,3; a[3]之後为0;
a[a.size() - 1] = 5; // a[4] = 0;
备注:
注1. C++的使用者,C++03或之前请用0代替NULL,C++11开始请改用nullptr
注2. gcc和clang支援VLA,Visual C++不支援
补充资料:
http://www.cplusplus.com/reference/vector/vector/resize/
--
个人网页:
http://gnitnaw.github.io/
以後在C_and_CPP或LinuxDev发表的文章都会放一份在这边。
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 86.209.153.222
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/C_and_CPP/M.1463129454.A.687.html
※ 编辑: wtchen (86.209.153.222), 05/13/2016 18:46:01
1F:→ Caesar08: c++11後,可以用std::array 05/13 19:01
2F:→ wtchen: 我都忘了还有这个,马上加 05/13 19:11
※ 编辑: wtchen (86.209.153.222), 05/13/2016 19:18:23
※ 编辑: wtchen (86.209.153.222), 05/13/2016 19:18:37
3F:→ wtchen: 对了,请问std::array是存在stack里吗? 05/13 19:24
4F:→ Caesar08: std::array就是一个C形式的array 05/13 19:30
5F:→ wtchen: 所以一样不能宣告太大? 05/13 19:31
6F:→ Caesar08: 对 05/13 19:34
※ 编辑: wtchen (86.209.153.222), 05/13/2016 19:40:38
※ 编辑: wtchen (86.209.153.222), 05/13/2016 19:40:56
7F:→ wtchen: 写到现在总觉得C跟C++5年内一定会分家... 05/13 19:46
8F:→ Caesar08: 最好快点分... 05/13 19:59
9F:→ wtchen: C++就像变心的女友一样回不来了.... 05/13 20:14
10F:→ tinlans: 永远检查 malloc 的传回值不是更好? XD 05/17 02:40
11F:→ wtchen: 我还真的很想在十三诫加这条 05/19 07:00