有没有一种方法可以在类似C的结构中执行自动字段重新排序?我的意思是使用语言功能(例如C和C ++的预处理器以及C ++的模板/类型特征/ etc),这使得可以执行以下宏(类似于Boost.Fusion的样式来适应结构):
REARRANGE(StructureName,
(int8_t)(FieldName1),
(int32_t)(FieldName2),
(int16_t)(FieldName3),
(int32_t)(FieldName4));
// is equivalent to (without loss of generality):
struct StructureName
{
int32_t FieldName2;
int32_t FieldName4;
int16_t FieldName3;
int8_t FieldName1;
};
Run Code Online (Sandbox Code Playgroud)
当然,方法应考虑字段的alignof值(以及sizeof),并在可能的情况下考虑#pragma pack当前值。
我知道结果的可移植性很差,但这仅用于本地使用。
必须将字段名称以及相应的类型保存在一起。
目的是减小总结构尺寸。
有时我在使用 GCC(4.6.4,Ubuntu 12.04)时遇到一个奇怪的问题,我用它来编译一个巨大的项目(数百个文件和数十万行代码),但我最近发现了一些东西。在某些编译之后(似乎是随机发生的),我得到一段特定的代码以不同的方式和错误地编译,导致我的代码中出现未定义的行为:
class someDerivedClass : public someBaseClass
{
public:
struct anotherDerived : public anoterBaseClass
{
void SomeMethod()
{
someMember->someSetter(2);
}
}
}
Run Code Online (Sandbox Code Playgroud)
其中“someSetter”定义为:
void someSetter(varType varName) { someOtherMember = varName; }
Run Code Online (Sandbox Code Playgroud)
通常,SomeMethod() 被编译为:
00000000019fd910 mov 0x20(%rdi),%rax
00000000019fd914 movl $0x2,0x278c(%rax)
00000000019fd91e retq
Run Code Online (Sandbox Code Playgroud)
但有时它会(错误地)编译为:
000000000196e4ee mov 0x20(%rdi),%rax
000000000196e4f2 movl $0x2,0x27d4(%rax)
000000000196e4fc retq
Run Code Online (Sandbox Code Playgroud)
setter 似乎被内联了,可能是因为编译标志 -O2:
-std=c++11 -m64 -O2 -ggdb3 -pipe -Wliteral-suffix -fpermissive -fno-fast-math -fno-strength-reduce -fno-delete-null-pointer-checks -fno-strict-aliasing
Run Code Online (Sandbox Code Playgroud)
但这不是问题。真正的问题是成员someOtherMember的偏移量,0x278c是正确的(第一种情况),但0x27d4不正确(第二种情况),这显然最终会修改类中完全不同的成员。为什么会发生这种情况?我缺少什么?(另外,我不知道我可以发布哪些其他相关信息,所以询问)。请记住,当再次编译项目(完全重新编译或仅编译修改后的文件)而不修改受影响的文件(或具有所使用的类的文件)时,会发生这种情况。例如,仅在完全不相关的文件中的某处添加一个简单的 printf() 可能会触发此行为或使其在发生时消失。我应该把这归咎于 -O2 吗?如果没有优化标志,我无法重现它,因为这是完全随机发生的。我正在使用make -j …
我正在尝试使用C++构造一个struct,如下所示:
struct kmer_value {
uint32_t count : 32;
uint32_t path_length : 32;
uint8_t acgt_prev : 4;
uint8_t acgt_next : 4;
}
Run Code Online (Sandbox Code Playgroud)
结构当前占用12个字节的内存,但我想将大小减小到9个字节.有没有办法实现它?
谢谢.
对于下面的结构,结构的实际(没有填充)大小为 54。在具有 MinGW (GCC) 4.8.1 x86_64 的 64 位 (Windows 7) 计算机上,我得到的大小sizeof(BMPHeader)为 56,这是可以理解的。根据BMP文件格式的要求,该结构不应有填充。我有三个选择(优先顺序):
alignas(1)struct __attribute__ ((packed)) BMPHeader#pragma pack(1)然而,最后一个选项(优先级最低)似乎单独工作,给了我 54。这是编译器中的错误还是我在这里完全误解了一些东西?南沙商会
#include <iostream>
struct alignas(1) BMPHeader
{
// BMP header
uint16_t magic;
uint32_t fileSize;
uint32_t reserved;
uint32_t dataOffset;
// DIB header
uint32_t dibHeaderLength;
uint32_t width;
uint32_t height;
uint16_t numColourPlanes;
uint16_t bitsPerPixels;
uint32_t biBitFields;
uint32_t dataSize;
uint32_t physicalWidth;
uint32_t physicalHeight;
uint32_t numPaletteColours;
uint32_t numImportantColours;
};
int main()
{
std::cout << sizeof(BMPHeader) << std::endl;
}
Run Code Online (Sandbox Code Playgroud) 我编写了一个简单的程序来测试使用memcpy将字节从字节缓冲区复制到结构中。但是我没有得到预期的结果。
我分配了100个字节的缓冲区,并将值设置为0、1、2 ... 99。然后,我将字节复制到16字节的结构中。
字节0x01丢失了。我试图了解正在发生的事情
#include <stdio.h>
#include <stdint.h>
struct Test {
uint8_t a;
uint16_t b;
uint32_t c;
uint64_t d;
uint8_t e;
};
int main(int argc, char** argv) {
uint8_t buffer[100];
for (uint8_t i = 0; i < 100; i++) {
buffer[i] = i;
}
struct Test test;
memcpy(&test, buffer, sizeof(struct Test));
printf("A is %ld and should be %ld\n", test.a, 0x00);
printf("B is %ld and should be %ld\n", test.b, 0x0201);
printf("C is %ld and should be %ld\n", test.c, 0x06050403);
printf("D …Run Code Online (Sandbox Code Playgroud) struct Point
{
double X;
double Y;
};
Run Code Online (Sandbox Code Playgroud)
Q1)是以下便携式(编译器/机器)
Point point = { 1.1, 2.2 };
double arr[2] = {};
memcpy(arr, point, sizeof(double)*2);
Run Code Online (Sandbox Code Playgroud)
Q2)结构数组相同
Point *pPoints = new Point[numPoints];
double *pArr = new double[2*numPoints];
memcpy(pArr, pPoints, sizeof(double)*2*numPoints);
Run Code Online (Sandbox Code Playgroud)
在Windows/MSVC上,我期待两者都能成功.
编辑:我不是为每个可能的结构/类别问这些问题; 我要求结构"Point"的这种特殊情况(注意:只有2个pod,没有virtualmember/user构造函数/用户构造函数).这可能是一个C问题,它与编译器的结构对齐和内存布局有关.
到目前为止,我已经知道c/c ++标准没有对Point的布局强制执行任何操作,因此我必须使用静态断言来确保它,对吗?
请考虑以下代码片段:
struct data_t {
int data1;
int data2;
struct data_t *next;
size_t size;
int data3;
int data4;
};
int *ptr;
struct data_t data;
...
ptr = &data.data4;
Run Code Online (Sandbox Code Playgroud)
现在使用指针,它被设置为指向结构中的最后一个元素,如何使用该指针访问结构中的第一个元素(data1)?
通常情况下,在这种情况下我要做的是用很多单词备份指针以指向该元素,但是存在问题.next结构中间的指针变量具有不同的大小,具体取决于平台.如果这是在32位平台上运行,那么指针是4字节,而在64位平台上,指针占用8个字节.size_t数据类型也会出现类似的问题.
虽然在示例中不清楚,但结构是内存块的标头,其大小可变并且是链接列表的一部分.AKA是内存分配器中的空闲列表.除了使用某种计算指针本身大小的初始化之外,是否有一种可移植的方法来获取结构的第一个元素的地址?
typedef struct __kstring_t {
size_t l, m;
char *s;
} kstring_t;
kstring_t * get_ptr_of_kstr(int num){
char * ch = (char *)malloc(num);
kstring_t kstr = {0, num, ch};
kstring_t *p = &kstr;
printf("In C, kstr.l: %zu\n", p->l);
printf("In C, kstr.m: %zu\n", p->m);
printf("In C, kstr.s: %p\n", p->s);
printf("In C, pointer to kstr: %p\n", p);
return p;
};
Run Code Online (Sandbox Code Playgroud)
type KStr
l::Csize_t
m::Csize_t
s::Ptr{Cchar}
end
Run Code Online (Sandbox Code Playgroud)
当我ccall用来调用get_ptr_of_kstr并获取kstring_tin 的指针时Julia,使用unsafe_load来获取其值,但值似乎是错误的.消息如下:
In C, kstr.l: 0
In …Run Code Online (Sandbox Code Playgroud) 让我们有这样的结构:
struct _Example {
int a;
int b;
int c;
} Example;
Run Code Online (Sandbox Code Playgroud)
一个函数通过指针获取此结构并输出struct成员的值.我想打印这样的值:
Example example;
func(&example);
if(example.a)
printf("%d", example.a);
if(example.b)
printf("%d", example.b);
if(example.c)
printf("%d", example.c);
Run Code Online (Sandbox Code Playgroud)
如何if用循环替换这些多个条件?
包含两个特征向量的C++类具有奇怪的大小.我的问题MWE在这里:
#include <iostream>
#include "Eigen/Core"
class test0 {
Eigen::Matrix<double,4,1> R;
Eigen::Matrix<double,4,1> T;
};
class test1 {
Eigen::Matrix<double,4,1> R;
Eigen::Matrix<double,3,1> T;
};
class test2 {
Eigen::Matrix<double,4,1> R;
Eigen::Matrix<double,2,1> T;
};
class test3 {
Eigen::Matrix<double,7,1> T;
};
class test4 {
Eigen::Matrix<double,3,1> T;
};
int main(int argc, char *argv[])
{
std::cout << sizeof(test0) << ", " << sizeof(test1) << ", " << sizeof(test2) << ", " << sizeof(test3) << ", " << sizeof(test4) << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我在我的系统上得到的输出(MacBook Pro,Xcode Clang ++编译器)是:
64,64,48,56,24 …
有以下结构:
typedef struct {
uint8_t val1;
uint16_t val2;
}some_config_type;
some_config_type EEMEM config = {
.val1 = 20,
.val2 = 2000
};
Run Code Online (Sandbox Code Playgroud)
该配置存储在eeprom内存中,我想从中加载它。我不确定avr gcc或C中是否有共同的规则,当我使用eeprom_read_block复制到另一个内存部分ram时,它保证了bot结构的布局是相同的。我想确保这在任何情况下都不会中断,并且内存布局是相同的,而不取决于部分。
下面的代码片段是故意访问下面的下一个sizeof(int)字节t[4],所以我知道这里犯的错误.我只是作为一个实验来看看编译器如何处理堆栈分配.
int t[5], i;
for (i = 0; i <= 5; i++) {
t[i] = 0;
}
Run Code Online (Sandbox Code Playgroud)
在Windows上执行此代码时,使用GNU C编译器的移植版本,程序总是陷入无限循环.我确信这只会发生,因为t并且i在堆栈上依次分配并t[5]指向与i变量相同的地址.因此,当执行t[5] = 0程序时实际将值设置i为零.
但是,当使用不同版本的GNU C编译器编译它时,我永远不会得到无限循环.地址t[5]与地址不同i.
我的问题是,为什么这种行为不同?我知道你不应该假设这个结果,但是不是堆栈分配应该以同样的方式发生吗?
我真正好奇的是编译器如何管理这些堆栈分配.有填充物吗?订单总是与源代码中的相同吗?显然,这与C标准无关,实现之间存在差异,甚至同一编译器的不同版本也存在差异.我很好奇,尽管在这种特殊情况下可能的结果和考虑因素是什么.