C++从C继承了数组,几乎无处不在.C++提供了易于使用且不易出错的抽象(std::vector<T>自C++ 98和C++ 11std::array<T, n>以来),因此对数组的需求并不像在C中那样频繁出现.但是,当您阅读遗产时代码或与用C编写的库交互,你应该牢牢掌握数组如何工作.
本FAQ分为五个部分:
如果您觉得此常见问题解答中缺少重要内容,请写下答案并将其作为附加部分链接到此处.
在下文中,"数组"表示"C数组",而不是类模板std::array.假定了C声明符语法的基本知识.请注意,面对异常,手动使用new和delete如下所示是非常危险的,但这是另一个常见问题解答的主题.
(注意:这是Stack Overflow的C++常见问题解答的一个条目.如果你想批评在这种形式下提供常见问题解答的想法,那么发布所有这些的元数据的发布将是这样做的地方.这个问题在C++聊天室中受到监控,其中FAQ的想法一开始就出现了,所以你的答案很可能被那些提出想法的人阅读.)
我已经看过它多次断言现在C++标准不允许使用以下代码:
int array[5];
int *array_begin = &array[0];
int *array_end = &array[5];
Run Code Online (Sandbox Code Playgroud)
&array[5]在这种情况下是合法的C++代码吗?
如果可能的话,我想要一个参考标准的答案.
知道它是否符合C标准也很有趣.如果它不是标准的C++,为什么决定做出从不同的治疗呢array + 5还是&array[4] + 1?
在下面的代码中为什么b[9]未初始化而不是越界?
#include <stdio.h>
int main(void)
{
char b[] = {'N', 'i', 'c', 'e', ' ', 'y', 'o', 'u', '!'};
printf("b[9] = %d\n", b[9]);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译器调用:
% gcc -O2 -W -Wall -pedantic -c foo.c
foo.c: In function ‘main’:
foo.c:6:5: warning: ‘b[9]’ is used uninitialized in this function [-Wuninitialized]
printf("b[9] = %d\n", b[9]);
% gcc --version
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.6) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. …Run Code Online (Sandbox Code Playgroud) int* p = 0;
int* q = &*p;
Run Code Online (Sandbox Code Playgroud)
这是未定义的行为吗?我浏览了一些相关问题,但这个具体方面没有显示出来.
以下代码是100%可移植的吗?
int a=10;
size_t size_of_int = (char *)(&a+1)-(char*)(&a); // No problem here?
std::cout<<size_of_int;// or printf("%zu",size_of_int);
Run Code Online (Sandbox Code Playgroud)
PS:问题仅限于学习目的.所以请不要给出答案Use sizeof()等
我不相信这是重复的(见下文)。†
我发现这个问题几乎是一个精确的重复,但是我认为答案无法分析漏洞。请参阅:*((*(&array + 1))-1)`是否可以安全地用于获取自动数组的最后一个元素?
我知道通常的方法是计算sizeof(array)/sizeof(*array)以获取数组中元素的数量。(并且在注释中已向我指出C ++具有std::size(array)。)
因此,我认为如果可以到达最后一个元素之后的地址,则可以使用指针数学运算来计算该数字。但是,后来我想到我可以:
&array + 1
Run Code Online (Sandbox Code Playgroud)
但是,此值的类型是指向数组的指针,因此要使数学正常工作,我需要取消引用此值。
const auto N = *(&array + 1) - array;
Run Code Online (Sandbox Code Playgroud)
在C和C ++中是否有允许这种取消引用合法的津贴?
我知道您可以指向数组最后一个元素之后的一个,但是您不能取消引用它。但是,此取消引用会产生一个数组对象,该对象立即衰减为指向其第一个元素的指针。
我可以使用a reinterpret_cast来避免使用取消引用运算符,但是我想知道在这种情况下C和/或C ++语言是否允许取消引用。
†我错过了类似的问题,但是这个问题有细微的不同。我已经了解了代码的工作原理,并且了解了将指针从数组的最后一个元素后移去通常存在问题。我要问的是,数组对象在表达式中使用时会衰减为指针的事实是否允许例外。我认为这可能是因为,取消引用指向对象的指针通常会导致对象值本身在表达式中使用(如果对象不存在,这将是一个问题)。
在我写的算法中,我可以得到以下内容(当然简化)
int a[3] = {1,2,3};
int b = a[3];
Run Code Online (Sandbox Code Playgroud)
当索引用于填充b溢出时,我从不使用b的值.代码仍然不正确吗?我是否必须进行明确的边界检查?
说我有一个像这样的数组:
int val[10];
Run Code Online (Sandbox Code Playgroud)
我故意用从负值到任何高于9的值来索引它,但没有以任何方式使用结果值.这可能是出于性能原因(也许在进行数组访问后检查输入索引会更有效).
我的问题是:
如果将地址取一个数组的末尾是合法的,那么如果数组地址的最后一个元素是0xFFFFFFFF?
这段代码将如何工作:
for (vector<char>::iterator it = vector_.begin(), it != vector_.end(); ++it)
{
}
Run Code Online (Sandbox Code Playgroud)
编辑:
我在这里读到在提出这个问题之前它是合法的:我可以采用数组的一个接一个元素的地址吗?
在C++ Primer的第2章"变量和基本类型"中,它说:
指向对象的指针和指向不同对象末尾的指针可以保持相同的地址.
我不是母语人士,我认为这就是为什么我对句子"一个指针越过一个对象的结尾"感到有点困惑.有人会告诉我这意味着什么吗?
我有一个阵列,
int a[size];
我想将所有数组元素设置为 1
因为数组中的某些索引已经设置为,1所以最好使用条件语句检查每个元素,如
for (int index = 0; index < size; index++)
{
if (a[index] != 1)
a[index] = 1;
}
Run Code Online (Sandbox Code Playgroud)
或者设置所有索引无论如何.会有什么区别?
我写了一个小程序:
void showrecord()
{
char *a[]={ "O_BILLABLE_ACCOUNT","O_CUSTOMER_TYPE_INDICATOR",
"O_A_PARTY_MSISDN_ID","O_A_PARTY_EQUIPMENT_NUMBER",
"O_A_PARTY_IMSI","O_A_PARTY_LOCATION_INFO_CELL_ID",
...
};
vector<std::string> fields(a,a+75);
cout<<"done!!!"<<endl;
}
int main()
{
showrecord();
}
Run Code Online (Sandbox Code Playgroud)
我有一些字符串文字,我希望它们被复制到一个向量中.我没有找到任何其他简单的方法:(.或者如果有任何直接的方法来初始化矢量而不使用数组,那将非常有用.这是在我在unix上运行可执行文件后转储核心.它给了我一个警告,但是:
Warning 829: "test.cpp", line 12
# Implicit conversion of string literal to 'char *' is deprecated.
D_TYPE","O_VARCHAR_5","O_VARCHAR_6","O_VARCHAR_7","O_VARCHAR_8","O_VARCHAR_9"};
Run Code Online (Sandbox Code Playgroud)
但是相同的代码在Windows上正常运行没有任何问题.我在HPUX上使用编译器aCC.
请帮忙! 下面的编辑是转储的堆栈跟踪.
(gdb) where
#0 0x6800ad94 in strlen+0xc () from /usr/lib/libc.2
#1 0xabc0 in std::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string<char,std::char_traits<char>,std::allocator<char>>+0x20 ()
#2 0xae9c in std<char const **,std::basic_string<char,std::char_traits<char>,std::allocator<char>> *,std::allocator<std::basic_string<char,std::char_traits<char>,std::allocator<char>>>>::uninitialized_copy+0x60 ()
#3 0x9ccc in _C_init_aux__Q2_3std6vectorXTQ2_3std12basic_stringXTcTQ2_3std11char_traitsXTc_TQ2_3std9allocatorXTc__TQ2_3std9allocatorXTQ2_3std12basic_stringXTcTQ2_3std11char_traitsXTc_TQ2_3std9allocatorXTc____XTPPCc_FPPCcT118_RW_is_not_integer+0x2d8
()
#4 0x9624 in showrecord () at test.cpp:13
#5 0xdbd8 in …Run Code Online (Sandbox Code Playgroud) 是否有可能在C++中做这样的事情(现在不能自己测试)?
int myarray[10] = {111,222,333,444,555,666,777,888,999,1234};
void functioncc()
{
int temparray = myarray;
for(int x=0; x<temparray.length; x++){
.... do something
}
}
Run Code Online (Sandbox Code Playgroud)
也许这个(但我不认为是):
int array1[5] = {0,1,2,3,4,5,6,7,8,9};
int array2[5] = {9,8,7,6,5,4,3,2,1,0};
void functioncc(int arid)
{
temparray[10] = "array"+arid;
........
}
Run Code Online (Sandbox Code Playgroud)
我可以在JavaScript中做类似的事情,但就像我说的那样 - 不要认为它在C++中是可能的.
谢谢你的时间.