相关疑难解决方法(0)

类C结构中自动字段重新排序的方法

有没有一种方法可以在类似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当前值。

我知道结果的可移植性很差,但这仅用于本地使用。

必须将字段名称以及相应的类型保存在一起。

目的是减小总结构尺寸。

c c++ struct alignment c++14

5
推荐指数
1
解决办法
306
查看次数

两次 GCC 编译相同的输入,生成两个不同的代码(第二个错误)

有时我在使用 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++ gcc

5
推荐指数
1
解决办法
395
查看次数

在C++中更有效地分配struct的内存

我正在尝试使用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个字节.有没有办法实现它?

谢谢.

c++ struct

4
推荐指数
1
解决办法
147
查看次数

使用 C++11 的 MinGW 和打包结构对齐

对于下面的结构,结构的实际(没有填充)大小为 54。在具有 MinGW (GCC) 4.8.1 x86_64 的 64 位 (Windows 7) 计算机上,我得到的大小sizeof(BMPHeader)为 56,这是可以理解的。根据BMP文件格式的要求,该结构不应有填充。我有三个选择(优先顺序):

  1. C++11的alignas(1)
  2. struct __attribute__ ((packed)) BMPHeader
  3. #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)

struct mingw g++ memory-alignment c++11

3
推荐指数
1
解决办法
1987
查看次数

C memcpy进行结构分配

我编写了一个简单的程序来测试使用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)

c memcpy

3
推荐指数
1
解决办法
50
查看次数

memcpy的pod结构数组到数组

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的布局强制执行任何操作,因此我必须使用静态断言来确保它,对吗?

c++

2
推荐指数
1
解决办法
770
查看次数

从指向结构中不同变量的指针访问结构的第一个变量

请考虑以下代码片段:

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是内存分配器中的空闲列表.除了使用某种计算指针本身大小的初始化之外,是否有一种可移植的方法来获取结构的第一个元素的地址?

c struct pointers

2
推荐指数
1
解决办法
403
查看次数

当我尝试从C中unsafe_load指针时,Julia得到错误的值

C代码:

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)

c julia

2
推荐指数
2
解决办法
189
查看次数

如何循环结构成员?

让我们有这样的结构:

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

2
推荐指数
1
解决办法
124
查看次数

包含特征向量的类的奇怪大小

包含两个特征向量的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 …

c++ sizeof padding memory-alignment eigen

1
推荐指数
1
解决办法
298
查看次数

在AVR的不同内存部分中进行结构打包

有以下结构:

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结构的布局是相同的。我想确保这在任何情况下都不会中断,并且内存布局是相同的,而不取决于部分。

c embedded struct avr alignment

0
推荐指数
1
解决办法
72
查看次数

关于C中堆栈分配的问题

下面的代码片段是故意访问下面的下一个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标准无关,实现之间存在差异,甚至同一编译器的不同版本也存在差异.我很好奇,尽管在这种特殊情况下可能的结果和考虑因素是什么.

c stack memory-management

-3
推荐指数
1
解决办法
197
查看次数