我正在搞乱多维数组和指针.我一直在看一个程序,它打印出一个简单数组的内容和地址.这是我的数组声明:
int zippo[4][2] = { {2,4},
{6,8},
{1,3},
{5,7} };
Run Code Online (Sandbox Code Playgroud)
我目前的理解是它zippo是一个指针,它可以保存其他几个指针的地址.默认情况下,zippo持有指针的地址zippo[0],也可以容纳指针的地址zippo[1],zippo[2]和zippo[3].
现在,请采取以下声明:
printf("zippo[0] = %p\n", zippo[0]);
printf(" *zippo = %p\n", *zippo);
printf(" zippo = %p\n", zippo);
Run Code Online (Sandbox Code Playgroud)
在我的机器上,它提供以下输出:
zippo[0] = 0x7fff170e2230
*zippo = 0x7fff170e2230
zippo = 0x7fff170e2230
Run Code Online (Sandbox Code Playgroud)
我完全理解为什么zippo[0]并*zippo拥有相同的价值.它们都是指针,它们都存储整数2的地址(默认),或者zippo[0][0].但是,zippo共享相同的内存地址又是什么呢?不zippo应该存储指针的地址zippo[0]?Whaaaat?
例如:
#include <stdio.h>
void why_cant_we_switch_him(void *ptr)
{
switch (ptr) {
case NULL:
printf("NULL!\n");
break;
default:
printf("%p!\n", ptr);
break;
}
}
int main(void)
{
void *foo = "toast";
why_cant_we_switch_him(foo);
return 0;
}
gcc test.c -o test
test.c: In function 'why_cant_we_switch_him':
test.c:5: error: switch quantity not an integer
test.c:6: error: pointers are not permitted as case values
Run Code Online (Sandbox Code Playgroud)
只是好奇.这是技术限制吗?
人们似乎认为只有一个常量指针表达式.这是真的吗?举例来说,这里是在Objective-C(一种常见的范例是真的是仅含有C除了NSString,id并且nil,这仅仅是一个指针,所以它仍然是相关的-我只是想指出,有是,事实上,一个共同的使用它,尽管这只是一个技术问题):
#include <stdio.h>
#include <Foundation/Foundation.h>
static NSString * const kMyConstantObject = @"Foo";
void why_cant_we_switch_him(id ptr) …Run Code Online (Sandbox Code Playgroud) 只是想知道它是如何在不同的编译器和调试/发布配置中实现的.标准是否以某种方式提供有关其实施的建议?它在哪里有所不同?
我试图运行一个简单的程序,我已经从函数返回非const引用和指向局部变量的指针,但它的工作方式相同.那么内部引用只是一个指针是真的吗?
int t[10];
int * u = t;
cout << t << " " << &t << endl;
cout << u << " " << &u << endl;
Run Code Online (Sandbox Code Playgroud)
输出:
0045FB88 0045FB88
0045FB88 0045FB7C
Run Code Online (Sandbox Code Playgroud)
输出u是有道理的.
我理解t并且&t[0]应该具有相同的价值,但是怎么样&t也一样?实际意味着什么?
指针只是一个地址吗?或者我错过了什么?
我测试了几种类型的指针:
但是指向成员函数的指针更大 - 我的平台上有16B.
三件事:
void*必须能够"包含"任何指针类型.换句话说,任何指针必须能够被转换为void*,对吧?如果是这样,那么为什么sizeof( void* )是8,而sizeof指向成员函数的指针是16?我有一张地图宣称为
std::map<std::string, Texture*> textureMap;
Run Code Online (Sandbox Code Playgroud)
我用它来将纹理文件的路径与实际纹理配对,这样我就可以通过路径引用纹理,而不会为单个精灵加载相同的纹理.我不知道该怎么做才能正确销毁ResourceManager类(地图所在的)的析构函数中的纹理.
我想过使用像这样的迭代器的循环:
ResourceManager::~ResourceManager()
{
for(std::map<std::string, Texture*>::iterator itr = textureMap.begin(); itr != textureMap.end(); itr++)
{
delete (*itr);
}
}
Run Code Online (Sandbox Code Playgroud)
但这不起作用,它说删除预期指针.现在已经很晚了,所以我可能只是错过了一些明显的东西,但我想让它在睡前工作.所以我是关闭还是我完全朝着错误的方向?
是否所有指针都是从指向结构类型的指针派生的问题都不容易回答.我发现这是一个重要问题,主要有以下两个原因.
A.缺少指向"任何"不完整或对象类型的指针,对方便的函数接口施加了限制,例如:
int allocate(ANY_TYPE **p,
size_t s);
int main(void)
{
int *p;
int r = allocate(&p, sizeof *p);
}
Run Code Online (Sandbox Code Playgroud)
[ 完整代码示例 ]
指向"任何"不完整或对象类型的现有指针明确描述为:
C99/ C11 §6.3.2.3 p1:
指向void的指针可以转换为指向任何不完整或对象类型的指针.[...]
从指向"任何"不完整或对象类型的现有指针派生的指针,指向void的指针,严格地是指向void的指针,并且不需要使用从指向"任何"不完整的指针派生的指针进行转换或对象类型.
B.程序员根据他们对特定实现的经验,使用基于不需要的假设的约定,有意识地或不知不觉地与指针的泛化相关,这种情况并不少见.假设,例如可转换,可表示为整数或共享公共属性:对象大小,表示或对齐.
根据C99 §6.2.5 p27/ C11 §6.2.5 p28:
[...]所有指向结构类型的指针应具有相同的表示和对齐要求.[...]
其次是C99 TC3 Footnote 39/ C11 Footnote 48:
相同的表示和对齐要求意味着可互换性作为函数的参数,函数的返回值和联合的成员.
虽然标准没有说:"指向结构类型的指针"并且选择了以下单词:"所有指向结构类型的指针",但它没有明确指定它是否适用于这种指针的递归推导.在标准中提到指针的特殊属性的其他情况下,它没有明确指定或提及递归指针派生,这意味着"类型派生"适用,或者它没有 - 但它没有明确提到.
虽然在引用类型时使用"所有指针"的措辞只使用两次,(对于结构和联合类型),而不是更明确的措辞:在整个标准中使用的"指针",我们不能总结它是否适用于这种指针的递归推导.
我很难理解C中数组名称的类型和用法.这可能看起来很长,但请耐心等待.
我理解以下语句声明a是类型,int []即整数数组.
int a[30];
Run Code Online (Sandbox Code Playgroud)
同时a也指出数组的第一个元素和类似*(a+2)的东西是有效的.因此,a看起来像一个指向整数的指针.但实际上类型int []和int*不同; 前者是数组类型,后来是指向整数的 指针.
类型int []变量int*在传递给函数时也会转换为类型变量; 因为C数组是通过引用传递的(sizeof运算符除外).
这就是让我垂涎的观点.看看下面这段代码:
int main()
{
int (*p)[3];
int a[3] = { 5, 4, 6 };
p = &a;
printf("a:%d\t&a:%d\n",a,&a);
printf("%d",*(*p + 2));
}
Run Code Online (Sandbox Code Playgroud)
OUTPUT:
a:2686720 &a:2686720
6
Run Code Online (Sandbox Code Playgroud)
那么,上面的代码是如何工作的呢?我有两个问题:
a并&a具有相同的值.为什么?int (*p)[3];做什么的?它声明了一个 …如果我声明并使用这样的指针:
int counter;
char *pCow = "pCow goes MOO";
for(counter = 0; counter < 14; counter++)
printf("%c", pCow[counter]);
Run Code Online (Sandbox Code Playgroud)
它显示整个字符串并且工作,是的,并且有很多欢乐.
但是,如果我使用这样的初始化器:
int counter;
char *pCow = {'p','C','o','w',' ','g','o','e','s',' ','M','O','O','\0'};
for(counter = 0; counter < 14; counter++)
printf("%c", pCow[counter]);
Run Code Online (Sandbox Code Playgroud)
程序崩溃了,pCow拒绝为我的享乐主义乐趣而呻吟!
3 Warnings. 0 Errors
line 11 (near initialization for 'pCow') [enabled by default] C/C++ Problem
line 11 excess elements in scalar initializer [enabled by default] C/C++ Problem
line 11 initialization makes pointer from integer without a cast [enabled by default] C/C++ Problem …Run Code Online (Sandbox Code Playgroud) (本示例中未使用#include,在带有g ++,选项-O0 -g3 -Wall -c -fmessage-length = 0的MacOS10.14,Eclipse IDE上编译)
假设此变量声明:
int (*fun)(int);
Run Code Online (Sandbox Code Playgroud)
无法使用“ std :: toupper和std :: tolower的无效重载”进行编译。
fun = (1 ? std::toupper : std::tolower); // ERROR, invalid overload
Run Code Online (Sandbox Code Playgroud)
这样编译就可以了:
if (1) {
fun = std::toupper; // OK
}
else {
fun = std::tolower; // OK
}
Run Code Online (Sandbox Code Playgroud)