char p [0]是代表自动分配的缓冲区还是安全指针?

时间:2018-08-01 05:46:34

标签: c++ c

这是C ++代码,显示编译器警告,但运行正常。预期的行为如下,但是:

char sz[] = "Hello World";
char *p;
snprintf(p, 12, sz);
printf("%s", p);

以上代码在运行时由于未分配* p而崩溃。好。

char sz[] = "Hello World";
char p[0];
snprintf(p, 12, sz);
printf("%s", p);

上面的代码工作正常,并且将显示“ Hello World”,而没有任何错误。 编译上面的代码时,显示编译器警告,使用[0]是非法的,但可以正常运行。

为什么会这样?

4 个答案:

答案 0 :(得分:5)

  

为什么会这样?

这仍然是未定义的行为。

它在您的设置中有效,因为碰巧,保存"Hello World"的数组与堆栈中的变量p相邻。

不要依赖此类代码,也不要使用它们。此类代码的行为可以随编译器的更改,使用不同的编译器选项等而改变。

答案 1 :(得分:1)

char p[0];

在链接程序确定的位置上定义长度为0的字符数组。
没有空间可以在其中打印任何内容。

相比唯一的区别/改进
char *p;

是后者甚至没有链接程序决定放置零大小空间的位置。

您需要打印空间。两种方法都不提供/保留任何方法。

更改为

char p[<N>];    

<N>是一个适当的大数字,以确保有足够的空间(如果您可以在编译前决定一个数字的话)。

使用

char* p;
/* ... */
p = malloc(<N>);

如果您在运行前不知道合适的大小。

答案 2 :(得分:1)

如您所料,第一个代码段通过访问未初始化的指针(无效的备忘录)来调用未定义的行为。好。

第二个片段是违反约束。对于p[0]之类的数组声明,请引用C11,第6.7.6.2章,(强调我的

  

除了可选的类型限定符和关键字static外,[]还可定界   表达式或*。如果它们定界表达式(指定数组的大小),则   表达式应具有整数类型。 如果表达式是常量表达式,则应为   的值大于零。 [....]

因此,该代码无效 ,您的编译器不应从该代码中生成二进制文件。提高编译器警告。

答案 3 :(得分:1)

private int buildDropDown(){
    ...
    final boolean ignoreBottomDecorations =
            mPopup.getInputMethodMode() == PopupWindow.INPUT_METHOD_NOT_NEEDED;
    final int maxHeight = mPopup.getMaxAvailableHeight(
            getAnchorView(), mDropDownVerticalOffset, ignoreBottomDecorations);
    ...
}


public int getMaxAvailableHeight(
        @NonNull View anchor, int yOffset, boolean ignoreBottomDecorations) {
    Rect displayFrame = null;
    final Rect visibleDisplayFrame = new Rect();

    anchor.getWindowVisibleDisplayFrame(visibleDisplayFrame);
    if (ignoreBottomDecorations) {
        // In the ignore bottom decorations case we want to
        // still respect all other decorations so we use the inset visible
        // frame on the top right and left and take the bottom
        // value from the full frame.
        displayFrame = new Rect();
        anchor.getWindowDisplayFrame(displayFrame);
        displayFrame.top = visibleDisplayFrame.top;
        displayFrame.right = visibleDisplayFrame.right;
        displayFrame.left = visibleDisplayFrame.left;
    } else {
        displayFrame = visibleDisplayFrame;
    }

    final int[] anchorPos = mTmpDrawingLocation;
    anchor.getLocationOnScreen(anchorPos);

    final int bottomEdge = displayFrame.bottom;
    ...

正确将获得未分配的错误内存

char sz[] = "Hello World";
char *p;
snprintf(p, 12, sz);
printf("%s", p);

一些编译器根据字符串长度分配大小,但是大多数情况下我们应该避免这种情况,这是与编译器相关的问题,与char sz[] = "Hello World"; char p[0]; snprintf(p, 12, sz); printf("%s", p);

没有关系