是否有 "nice" 方法可以将指向结构的指针前进一个字节?
Is there a "nice" way to advance a pointer to a struct by one byte?
我有一个指向一个结构的指针,我想将它移到
地址范围,逐字节。我有一个有效的方法,但是
在我眼里很丑。不幸的是,"nice" 方法不起作用。这是一个最小的例子:
#include <stdint.h>
typedef struct {
uint32_t a;
uint32_t b;
} s_t;
int main( int argc, char** argv )
{
uint32_t address = 17;
s_t* ps = (s_t*) address;
// ugly
uint8_t* gna = (uint8_t*) ps;
++gna;
ps = (s_t*) gna;
// nice
++((uint8_t*) ps);
}
编译器在"nice"部分报错:
% gcc test.c -o test.bin
test.c: In function 'main':
test.c:17:5: error: lvalue required as increment operand
++((uint8_t*) ps);
^
我理解错误,但我认为转换为 uint8_t* 会
创建一个左值。显然,我错了。
有没有办法让它变得更好?
作为解决方案,可以定义一个 char*
指向该结构的指针。然后通过添加这个指针,你可以访问指向结构的字节。
s_t a;
unsigned char *b = (unsigned char*)&a;
unsigned char next_byte = *(++b);
然后加上b
就可以得到a
的字节数。此解决方案的不足 是您可能会在某些编译器中收到错误或警告,以通过 char 指针将指针传递给结构。
显然 (uint8_t*)
之类的类型转换不会产生左值。由于您的代码是用 C++ 编写的,因此您可以使用此转换 (uint8_t*&)
.
怎么样:
ps = (s_t*) (1 + (uint8_t*) ps);
这没有多大意义。如果您将结构指针增加 1 个字节,您最终会得到一个未对齐的地址,这在大多数系统上都是有问题的。我必须假设您的系统不是任何主流的 32/64 位 CPU(不是 x86、ARM、PowerPC 等),否则您的问题毫无意义。
要将地址增加一个字节,只需这样做:
ps = (s_t*) ((uintptr_t)ps + 1);
关于发布的代码:
#include <stdint.h>
// for flexability, do not overlap the 'typedef' with the struct definition
// (and always use a struct tag name)
typedef struct {
uint32_t a;
uint32_t b;
} s_t;
int main( int argc, char** argv ) <-- causes 2 compiler warning messages
// due to unused parameters
// suggest: int main( void )
{
uint32_t address = 17;
s_t* ps = (s_t*) address; <-- 17 is not a valid address for a struct.
// ugly <-- however, it actually works
uint8_t* gna = (uint8_t*) ps;
++gna;
ps = (s_t*) gna; <-- don't do this,
// use 'gna' to access the individual bytes
// nice
++((uint8_t*) ps); <-- does not compile
}
我有一个指向一个结构的指针,我想将它移到 地址范围,逐字节。我有一个有效的方法,但是 在我眼里很丑。不幸的是,"nice" 方法不起作用。这是一个最小的例子:
#include <stdint.h>
typedef struct {
uint32_t a;
uint32_t b;
} s_t;
int main( int argc, char** argv )
{
uint32_t address = 17;
s_t* ps = (s_t*) address;
// ugly
uint8_t* gna = (uint8_t*) ps;
++gna;
ps = (s_t*) gna;
// nice
++((uint8_t*) ps);
}
编译器在"nice"部分报错:
% gcc test.c -o test.bin
test.c: In function 'main':
test.c:17:5: error: lvalue required as increment operand
++((uint8_t*) ps);
^
我理解错误,但我认为转换为 uint8_t* 会 创建一个左值。显然,我错了。
有没有办法让它变得更好?
作为解决方案,可以定义一个 char*
指向该结构的指针。然后通过添加这个指针,你可以访问指向结构的字节。
s_t a;
unsigned char *b = (unsigned char*)&a;
unsigned char next_byte = *(++b);
然后加上b
就可以得到a
的字节数。此解决方案的不足 是您可能会在某些编译器中收到错误或警告,以通过 char 指针将指针传递给结构。
显然 (uint8_t*)
之类的类型转换不会产生左值。由于您的代码是用 C++ 编写的,因此您可以使用此转换 (uint8_t*&)
.
怎么样:
ps = (s_t*) (1 + (uint8_t*) ps);
这没有多大意义。如果您将结构指针增加 1 个字节,您最终会得到一个未对齐的地址,这在大多数系统上都是有问题的。我必须假设您的系统不是任何主流的 32/64 位 CPU(不是 x86、ARM、PowerPC 等),否则您的问题毫无意义。
要将地址增加一个字节,只需这样做:
ps = (s_t*) ((uintptr_t)ps + 1);
关于发布的代码:
#include <stdint.h>
// for flexability, do not overlap the 'typedef' with the struct definition
// (and always use a struct tag name)
typedef struct {
uint32_t a;
uint32_t b;
} s_t;
int main( int argc, char** argv ) <-- causes 2 compiler warning messages
// due to unused parameters
// suggest: int main( void )
{
uint32_t address = 17;
s_t* ps = (s_t*) address; <-- 17 is not a valid address for a struct.
// ugly <-- however, it actually works
uint8_t* gna = (uint8_t*) ps;
++gna;
ps = (s_t*) gna; <-- don't do this,
// use 'gna' to access the individual bytes
// nice
++((uint8_t*) ps); <-- does not compile
}