在指针表示法上使用数组表示法,反之亦然

时间:2016-10-01 22:59:04

标签: c++

从我所见,指针符号和数组符号有很大的重叠。每种符号方法的独特之处是什么?在什么情况下使用一种方法比另一种方法更有益?

int main(){
    int arr[]={1,2,3,4};
    int * arrPtr = arr;
    for (int i = 0; i < 4; ++i){
        cout<<arr[i]<<" "<<arrPtr[i]<<" "<<*(arr+i)<<" "<<*(arrPtr+i)<<endl;
    }  
    return 0;
}

3 个答案:

答案 0 :(得分:1)

T [N]类型的对象知道编译时N是什么。 T *的对象不知道目标地址有多少T。

此代码:

#include <iostream>

int main()
{
    int a[10];
    int* b = new int[10];

    std::cout << sizeof(a) << ", " << sizeof(b) << "\n";
}

输出40, 4http://ideone.com/GANFtB)。

数组衰减指向指针(参见http://c-faq.com/~scs/cgi-bin/faqcat.cgi?sec=aryptr),以便在编写时

void f(int a[])

你实际上正在使用原型

创建一个函数
void f(int a*)

此时,您不再知道a的维度。

但是,指针和数组旨在相互补充。当你有

int a[4] = { 1, 2, 3, 4 };

a很乐意为你指出一个指针

int a[4] = { 1, 2, 3, 4 };
int *p = a;

std::cout << a[0] << p[0] << *a << *p << *(a+1) << *(p+1);

将打印111122http://ideone.com/G61NL1

使用固定大小的数组意味着: - 作为局部变量,它将在堆栈中。优点:速度,局部性,缺点:大小受到限制,大小必须在编译时知道。 - 作为全局变量:程序二进制文件中的固定大小分配,编译时需要的大小。 - 作为成员变量:将对象大小增加一个已知数量,编译时所需的大小。

指针允许您分配动态内存,但需要传递大小参数:

void f(int* a, size_t elements);

使用数组,您可以使用技巧编写特定于大小的代码:

void f(int (*a)[10]);  // require input to be an array of 10 elements

int a[4];
f(&a);  // error: int (*)[4] can't convert to int (*)[10]

和模板技巧:

template<size_t N>
void dump(int (&a)[N])   // takes arrays with known size only
{
    std::cout << "[" << a[0];
    for (size_t i = 1; i < N; ++i)
        std::cout << ',' << a[i];
    std::cout << "]";
}

int main() {
    int a[] = { 1, 2, 3, 4 };  // compiler calculates size
    dump(a);
}

http://ideone.com/ATB81u

所有这一切都说,语言都没有实现边界检查:

int main() {
    int a[10];
    a[100] = 1;  // compiles and links
}

如果您使用std::arrayat运算符,则可以获得经过边界检查的数组访问权限。

std::array a<int, 4>;
a.at(20);  // detected as runtime error and not UB

答案 1 :(得分:0)

  

在什么情况下使用一种方法比另一种方法更有益?

实际上并没有什么区别,所以我们无法判断使用其中一个是否有任何优势。

而是使用std::vector<int>std::array<int,4>关于c ++。

答案 2 :(得分:-1)

int arr[] vs int * arrPtr

int arr[]int * arrPtr之间的区别在于编译器&#34;知道&#34;一个是数组,另一个是指针;)

例如:

int arr[] = { 1, 2, 3, 4 };
int * arrPtr = arr;
cout << "sizeof(arr): " << sizeof(arr) << endl
    << "sizeof(arr[0]): " << sizeof(arr[0]) << endl
    << "sizeof(arrPtr): " << sizeof(arrPtr) << endl
    << "sizeof(arrPtr[0]): " << sizeof(arrPtr[0]) << endl;

可能会打印如下内容:

sizeof(arr): 16
sizeof(arr[0]): 4
sizeof(arrPtr): 8
sizeof(arrPtr[0]): 4

arr[0]arrPtr[0]是相同的,但arrarrPtr不是。你可以使用这个事实。

Bounds Checking?

Arrays还为编译器提供了进行边界检查的机会,但这是有限的。

静态检查至少可以在某些编译器上运行。例如。这不能在VCC中编译:

int arr[] = { 1, 2, 3, 4 };
arr[4] = 7;

但是没有办法对此提出保护:

arr[x] = 7;

还有一些函数可以根据数组大小实现运行时保护。例如,这不会在s1

之后覆盖内存
char s1[] = "aaa";
sprintf_s(s1, "sssssssssssssssssss");

失败了,因为sprintf_s&#34;知道&#34;大小s1(大小实际上是sprintf_s的模板参数)。

arr[i] vs *(arr + i)

对于整数数组,arr[i]*(arr + i)之间没有区别。但是对于你自己的指针式类,你可以覆盖[]+运算符,使它们与众不同。