我正在编写和读取内存映射中的寄存器,如下所示:
//READ
return *((volatile uint32_t *) ( map + offset ));
//WRITE
*((volatile uint32_t *) ( map + offset )) = value;
Run Code Online (Sandbox Code Playgroud)
但是编译器给了我这样的警告:
warning: pointer of type ‘void *’ used in arithmetic [-Wpointer-arith]
Run Code Online (Sandbox Code Playgroud)
如何更改我的代码以删除警告?我正在使用C++和Linux.
下面的行(纯c)在windows(win7 64位+代码块13 + mingw32)和debian(wheezy 32位+代码块10 + gcc)上干净地编译,但在kali(64位+代码块+ gcc)上引发警告.任何意见?我的意思是,为什么我会收到这个警告,虽然同一行编译没有窗口和debian上的任何警告?
void* foo(void *dst, ...) {
// some code
unsigned int blkLen = sizeof(int); // this line ok.
unsigned int offset = (unsigned int) dst % blkLen; // warning here!
// some code cont...
}
Run Code Online (Sandbox Code Playgroud)
codeblocks中的消息是:" error:从指针转换为不同大小的整数[-Werror = pointer-to-int-cast]"
注意:我的编译器选项是-std=c99 -Werror -save-temps(在所有三个系统上都相同).
编辑2:虽然我已经设法使用下面的预处理器行编译无警告,但@Keith Thompson(见下文)对此问题有一个关键点.所以,我最后的决定是使用uintptr_t将是一个更好的选择.
编辑1:谢谢大家的回复.正如所有回复所述,问题是32位与64位问题.我插入了以下预处理行:
#if __linux__ // or #if __GNUC__
#if __x86_64__ || __ppc64__
#define ENVIRONMENT64
#else
#define ENVIRONMENT32
#endif
#else …Run Code Online (Sandbox Code Playgroud) 我发现自己处于以下情况:
#include <stdio.h>
typedef struct T1 { int id; } T1;
typedef struct T2 { int id; } T2;
void f(T1 *ptr) { printf("f called\n"); }
int main(void)
{
T2 obj;
T2 *ptr = &obj;
f(ptr); // shouldn't this be a compilation error ?
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当然,这是无效的C++,但在C中,程序打印 "f called".这有效吗?
(以防万一不清楚)如果"结构上"不同,程序仍然可以编译和运行T2,例如
typedef struct T2 { double cc[23]; } T2;
Run Code Online (Sandbox Code Playgroud) 为什么一个能投射出std::ostream的void指针?我不知道有任何这样的转换运算符std::ostream.代码如下
#include <iostream>
int main()
{
void *p = std::cout; // why does this work?
}
Run Code Online (Sandbox Code Playgroud)
我问这个问题,因为我已经看到new调用了一个放置操作符
Foo* pFoo = new (std::cerr) Foo;
Run Code Online (Sandbox Code Playgroud)
并且完全不知道为什么会写这样的东西.
PS:我正在使用或不使用g ++ 4.9.2进行编译-std=c++11.clang ++ 不接受代码.
PSS:发现由于所谓的"安全bool问题"(参见@ nicebyte的回答),在预C++ 11 void*中定义了一个转换运算符std::ostream,然后在C++ 11中将其删除.但是,我的代码使用g ++在C++ 11中编译得很好.更重要的是,clang ++拒绝它,无论我使用什么版本的标准,即使有-std=c++98,尽管我的理解是它应该接受,如果编译为pre-C++ 11.
我有一个程序写入我正在试验的游戏的记忆.当我使用常规静态地址时,代码对我很有用,但出于某种原因,一旦找到工作指针,我似乎无法做到这一点.例如,我在指针扫描几次后在Cheat Engine中找到了这个:
每次加载游戏并编辑值时,此地址都有效.问题是我不明白如何在我的程序中使用它.这是我尝试插入值的声明变量:
bool UnlimitedAmmo = false;
string AmmoPointer = "031B7324"; // <--- The address
int[] AmmoOffset = { 0x2c, 0x1e8, 0x3c8, 0x6d4, 0x508 }; // <--- It's pointers
int AmmoToFill = 1337; // <--- The Amount of ammo to give
Run Code Online (Sandbox Code Playgroud)
我传递这些变量如下:
MyMemory.ReadProcess = MyProcess[0];
MyMemory.Open();
int PointerAddress = HexToDec(AmmoPointer);
int[] PointerOffest = AmmoOffset;
int BytesWritten;
byte[] ValueToWrite = BitConverter.GetBytes(AmmoToFill);
string WrittenAddress = MyMemory.PointerWrite((IntPtr)PointerAddress, ValueToWrite,
PointerOffest, out BytesWritten);
MyMemory.CloseHandle();
Run Code Online (Sandbox Code Playgroud)
我曾经使用静态地址(对于不同的游戏),一旦插入地址和偏移量,我的代码工作正常.这次我很难过.任何帮助和解释都将深表感谢.提前致谢.
我仍然想知道为什么在C中你不能简单地使用普通变量设置一些东西.变量本身是指向数据的指针,不是吗?那么为什么当你可以简单地使用原始变量时,指针指向变量中的数据呢?它是否可以访问所述变量中的特定位(或字节,我猜)?
我确信这是合乎逻辑的,但是我从来没有完全掌握这个概念,当阅读代码时*pointers总是把我抛弃.
昨天我上课了,在某个时候讲师正在谈论C代码.他说:
在C中制作指针的目的是什么?唯一的目的是使编译器正确解释指针操作(例如,添加int指针将导致与添加char指针不同的偏移量).除此之外,没有区别:所有指针在内存中的表示方式相同,无论指针指向int值,char值,short值还是其他.因此,转换指针不会修改内存中的任何内容,它只会帮助程序员进行与其正在处理的指针类型更相关的操作.
但是,我已经阅读,特别是在Stack Overflow中,这不是100%真实.我已经读过,在一些奇怪的机器中,不同类型的指针可以以不同的方式存储在内存中.在这种情况下,如果将代码编译为此类机器,则不将指针更改为正确的类型可能会导致问题.
基本上,这是我正在谈论的那种代码.请考虑以下代码:
int* int_pointer;
char* char_pointer;
int_pointer = malloc(sizeof(int));
*int_pointer = 4;
Run Code Online (Sandbox Code Playgroud)
现在有两种选择:
1.
char_pointer = (char *)int_pointer;
Run Code Online (Sandbox Code Playgroud)
2.
char_pointer = int_pointer;
Run Code Online (Sandbox Code Playgroud)
案例2的代码可能成为一个问题?制作演员表(案例1)最终会改变内存中的指针格式(如果是的话,你能给出一个机器的例子吗?)?
谢谢
在调试一些嵌入式代码时,我遇到了类似这样的事情:
buffPtr = &a[5];
buffEndPtr = &a[10];
while (buffPtr != buffEndPtr)
{
*buffPtr = 0xFF;
buffPtr = &buffPtr[1]; /* MISRA improvement for: buffPtr++ */
}
Run Code Online (Sandbox Code Playgroud)
为什么这个结构会改进(*buffPtr)++?
有两个相关的C标准规则:
C99标准,6.3.2.3:
指向void的指针可以转换为指向任何不完整或对象类型的指针.指向任何不完整或对象类型的指针可能会转换为指向void的指针并再次返回; 结果应该等于原始指针.
而且7.20.1.4:
以下类型指定一个无符号整数类型,其属性是任何有效的void指针都可以转换为此类型,然后转换回指向void的指针,结果将等于原始指针:
uintptr_t
这意味着,以下代码符合:
int *p = NULL;
void *q = (void*)p;
uintptr_t s = (uintptr_t)q;
Run Code Online (Sandbox Code Playgroud)
但它真的需要两步演员吗?如果执行以下操作,编译器是否会执行隐式中间转换:
int *p = NULL;
uintptr_t s = (uintptr_t)p;
Run Code Online (Sandbox Code Playgroud)
(好吧,它可能会出现在大多数编译器上,但我的问题是关于标准符合性)
我试图理解将多维数组传递给c中的函数的"最佳实践"(或实际上是任何实践).当然这取决于应用程序,因此我们考虑编写一个函数来打印可变大小的2D数组.特别是,我对如何printArry(__, int a, int b)在下面的代码中编写函数感兴趣.我省略了第一个参数,因为我不确定应该是什么.
void printArry(_____, int a, int b){
/* what goes here? */
}
int main(int argc, char** argv){
int a1=5;
int b1=6;
int a2=7;
int a2=8;
int arry1[a1][b1];
int arry2[a2][b2];
/* set values in arrays */
printArry(arry1, a1, b1);
printArry(arry2, a2, b2);
}
Run Code Online (Sandbox Code Playgroud) c arrays pointers multidimensional-array variable-length-array