增加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/