【发布时间】:2015-07-19 16:51:17
【问题描述】:
我正在学习编程范式教程并进行一些与内存相关的练习。我刚刚提取了两个问题(请忘记代码的样子,对不起,这是错误的代码,但我只想从中学习指针的东西)。原始代码使 lsearch 尽可能通用,因此它使用所有指针。
-
我有一个关于访问数组元素的问题:
当我们访问数组
a[]的第四个元素时,我们使用*(a+3); 当我们访问字符串数组char * names[]的第三个元素时,我们使用*(char**)((char*)names+sizeof(char*)*2)。 我们是否假设数组的元素是连续保存在内存中的? 关于访问字符串数组元素的问题2:为什么我们需要在
names(基地址)前面添加(char*),我尝试不添加(char*)并且代码因分段错误而崩溃错误。我打印了(char*)的大小,是8,而sizeof(names)是32。这里为什么需要(char*)?我真的认为地址是 32 位,如果我们将其转换为 8 位,计算机应该很难找到它指向的元素。 谢谢你
#include<iostream>
#include<string>
#include<typeinfo>
int main()
{
int a[5] = {1,2,3,4,5};
std::cout << *(a+3) << std::endl;
char* names[4] = {"James", "Dustin", "Rich", "Ed"};
std::cout << *(char**)((char*)names+2*sizeof(char*)) << std::endl;
//std::cout << sizeof(names) << " " << sizeof(char*) << std::endl;
}
这是来自 stanford 107 的原始代码。
#include<iostream>
#include<string.h>
#include<stdio.h>
using namespace std;
int StrCmp(void* vp1, void* vp2)
{
char *s1 = *(char**)vp1;
char *s2 = *(char**)vp2;
if(strcmp(s1,s2)==0){
return 0;
}
return 1;
}
char ** lsearch(void *key, void* base, int size, int elemSize, int (*cmpFn)(void *, void *))
{
for(int i=0; i<size; ++i){
char* addr = (char*) base + elemSize *i;
if (cmpFn(key, addr)==0) return (char**)addr;
}
return NULL;
}
int main()
{
char *notes[] = {"Ab", "F#", "B", "Gb", "D"};
char* favorStr = "F#";
char ** found = lsearch(&favorStr,notes,5,sizeof(char*),StrCmp);
if(found!=NULL) cout << *(char**)found << endl;
else cout << "not found" << endl;
}
【问题讨论】:
-
sizeof返回字节大小,而不是位(并且您的指针显然是 64 位宽)。 -
这个问题表明之前的研究很少,其中一些是错误的。检查标准将回答您有关连续性的问题。检查一些关于数组和/或指针的(更好的)教程将使您摆脱诸如
*(char**)((char*)names+2*sizeof(char*))之类的神秘结构 -
另外,如果你想使用 C++,你应该避免使用旧的 C 风格的字符串。并不是说它们像您的帖子声称的那样困难,但是为什么要活在过去呢?使用现代 C++ 功能,您完全不必担心事物是否连续、指针的宽度等。
-
那不是 C 代码。还有非常糟糕的 C++ 代码。
-
@underscore_d:只是为了说明清楚:实际上也不会用 C 语言编写它。而且,这不是“旧的 C 风格字符串”,但那是 C 的工作方式。没有什么“旧的”。两种语言都有其用例,不应被视为“旧式”。实际上,C++ 的“过去”并不比 C 少很多。