9

您好,我有以下测试代码,我对 cpp 感到困惑。

  1. 如果您在 library.h 中声明一个带有空元素子句的数组.. 编译器会选择什么?它也没有抱怨,我使用 Cygwin。

  2. 在 library.cpp 中,我将值分配给两个元素,编译器是否假设一个包含一个元素的数组,而我将第二个元素写入数组范围之外?

图书馆.h

#ifndef LIBRARY_H
#define LIBRARY_H

class library {

public:
    void print();
    char a[];
};

#endif

图书馆.cpp

#include <stdio.h>
#include "library.h"

void library::print() {
    a[0] = 'a';
    printf("1. element: %d\n", a[0]);
    a[1] = 'b';
    printf("2. element: %d\n", a[1]);
}

客户端.cpp

#include <stdio.h>
#include "library.h"

void execute();
library l;

int main() {
    l = library();
    l.print();
    return 0;
}

生成文件

OPTIONS=-Wall

all: main

run: main
        ./main.exe

main: client.o library.o
        g++ $(OPTIONS) -o main $^

library.o: library.cpp library.h
        g++ $(OPTIONS) -c $<

.cpp.o:
        g++ $(OPTIONS) -c $<

clean:
        rm -r *.o
4

4 回答 4

11
  1. 没有称为 C/C++ 的语言,因此您的 Q 不能同时标记。
  2. 由于您使用的是类,因此您的程序只能是 C++ 而不是 C。

public:
     void print();
     char a[];

这段代码在 C++ 中简直是非法的。C++ 中的数组大小需要是正的编译时间常数。解决方案是将其替换为:

public:
      void print();
      std::string a;

注意声明,

char a[];

在 c99 中有效,被称为不完整数组类型,C 标准保证a可以存储至少一个该类型的元素char。这在 C++ 中无效。C++ 标准不允许这些。仅仅因为两者是不同的语言。

于 2013-03-19T08:38:35.467 回答
6

首先,它不是合法的 C++。这是一个古老的 hack,C 仅在 C98 中使其合法。基本思想是struct只能动态分配(使用malloc),并且在它之后为对象分配所需的内存。所以你会做类似的事情malloc( sizeof( library ) + strlen( s ) + 1 )。hack 用于避免额外的分配。

使用此 hack 的类不能与 一起使用new,也不能是成员或基类。(它也不能是 C 中的成员。)

您可以在 C++ 中进行模拟:

class Library
{
    //  ...
    char* buffer() { return reinterpret_cast<char*>( this + 1 );
    void* operator new( size_t n, size_t extra )
    {
        assert( n == sizeof( Library ) );
        return ::operator new( n + extra );
    }
};

但是请注意,与 C 解决方案不同,这存在对齐问题的风险。它适用于字符类型,如果该类的其他成员需要至少与缓冲区类型一样多的对齐,它会起作用,但否则它可能会失败。(g++ 中 std::basic_string 的实现使用了它——如果用 . 实例化会在某些机器上崩溃double。)

于 2013-03-19T08:49:51.917 回答
5

空数组声明一个长度为零的数组。它在 C 中通过将结构 S 放置在大于 sizeof(S) 的内存区域中,然后使用数组访问剩余内存来使用:

memory* ptr = malloc(sizeof(memory) + sizeof(char) * 10);
// you can now manipulate ptr->a as an array of 10 elements

这是一个在 C++ 中用处不大的技巧。只需使用 std::vector 代替。

于 2013-03-19T08:31:14.350 回答
1

它通常被称为 C 中的struct hack。它使用一种称为灵活数组成员的功能。

然而,这不是任何 C++ 标准规范的一部分。看看这个问题

请注意,观察到某些东西确实有效并不意味着您可以依赖它来可靠地工作。如果行为未定义,从技术上讲,任何事情都可能发生。包括猛龙突然进攻。

在 C++ 中,您可能会使用 astd::vector<char>或 a std::string

于 2013-03-19T08:41:06.227 回答