【问题标题】:Why does a pointer work and not a normal variable in this code?为什么在这段代码中指针起作用而不是普通变量?
【发布时间】:2016-09-13 07:32:27
【问题描述】:

在下面的代码中,我收到了以下警告:

在函数“on_btn_Convert_clicked”中:|

警告:赋值从没有强制转换的指针生成整数 [已启用 默认]|

警告:传递“gtk_label_set_text”的参数 2 使指针从 没有强制转换的整数 [默认启用]|

||=== 构建完成:0 次错误,2 次警告(0 分钟,1 秒)===|

如果我按原样运行程序,它将打开 GUI,但是当按下相关按钮时会导致分段错误并使程序崩溃。

#include <stdlib.h>
#include <stdio.h>
//include gtk headers
#include <gtk/gtk.h>

//define pointer variable names
GtkWidget  *plblFileName;
GtkWidget  *pbtnConvert;
GtkWidget  *pbtnFileChooser;


//prototype functions
char on_btn_Convert_clicked();

char on_btn_Convert_clicked()
{
   //define variables
   char hello;

   hello = "hello!";

   gtk_label_set_text(GTK_LABEL(plblFileName), hello);
   return 0;
}

//start main loop
int main( int    argc,
      char **argv )
{
    GtkBuilder *builder;
    GtkWidget  *window;
    GError     *error = NULL;

    //Init GTK+
    gtk_init( &argc, &argv );

    //Create new GtkBuilder object
    builder = gtk_builder_new();
    //Load UI from file. If error occurs, report it and quit application.
    //Replace "tut.glade" with your saved project.
    if( ! gtk_builder_add_from_file( builder, "testGTK.ui", &error ) )
    {
        g_warning( "%s", error->message );
        g_free( error );
        return( 1 );
    }

    //Get main window pointer from UI
    window = GTK_WIDGET( gtk_builder_get_object( builder, "windowMain" ) );

    // get pointer to the label and button
    plblFileName = GTK_WIDGET(gtk_builder_get_object(builder, "lbl_FileName"));
    pbtnConvert = GTK_WIDGET(gtk_builder_get_object(builder, "btn_Convert"));
    pbtnFileChooser = GTK_WIDGET(gtk_builder_get_object(builder, "btn_Choose"));

    //connect the button with its signal
    g_signal_connect(G_OBJECT(pbtnConvert), "clicked", G_CALLBACK(on_btn_Convert_clicked), NULL);

    //Destroy builder, since we don't need it anymore
    g_object_unref( G_OBJECT( builder ) );

    //Show window. All other widgets are automatically shown by GtkBuilder
    gtk_widget_show( window );

    //Start main loop
    gtk_main();

    return( 0 );
}

但是,如果我将变量“hello”设为指针,那么错误就会消失,一切正常。

像这样:

char on_btn_Convert_clicked()
{
   //define variables
   char *hello;

   hello = "hello!";

   gtk_label_set_text(GTK_LABEL(plblFileName), hello);
   return 0;
}

我不明白一个指针,即只指向内存中某个位置的对象,如何可以等于“hello”并且仍然像这样工作?

谁能向我解释为什么'char hello'变量需要是一个指针(*)而不能只是一个字符串或'char[]'?

最后,您能总结一下为什么这与使用普通 char 变量的版本相比有效吗?

【问题讨论】:

  • 使用=和指针意味着使指针指向另一个操作数所指示的内存位置

标签: c string variables pointers string-literals


【解决方案1】:

因为在你的代码的第一部分

char hello;
hello = "hello!";

是错误的,因为您的编译器已经警告过您。

"Hello!" 形式的 string literal 返回指向第一个元素的指针,即字符串中第一个元素的地址,不能存储到 char 中。你需要一个char * 来保存它。

或者,您可以使用数组char hello[] = "hello!";。这将创建一个数组并使用字符串文字“hello!”初始化该数组,这也应该可以正常工作,但是一个简单的(标量)char 无论如何都行不通。

【讨论】:

    【解决方案2】:

    "hello" 这样的常量字符串文字实际上是一个包含六个字符的数组('h''e''l''l''o' 和终止符 '\0')。当您使用它时,它可以衰减为指向其第一个元素的指针。

    这就像有一个实际的数组:

    char hello_array[6] = { 'h', 'e', 'l', 'l', 'o', '\0' };
    

    然后将其分配给类似的指针

    char *hello = &hello_array[0];
    

    上面的内容基本上是你做的时候发生的事情

    char *hello = "hello";
    

    当你有

    char hello = "hello";
    

    好像在做

    char hello = &hello_array[0];
    

    这根本行不通。调用函数时也是如此,它需要一个char * 类型的参数,而你传递一个char 类型的参数。这两种类型在很长一段时间内并不相同。


    另一种解释方式可能是您可以这样想:变量是存储值的地方。当您有char 类型的变量时,您可以存储单个字符。当您有一个指向字符的指针时,您可以准确地存储它,一个指向字符(实际上是内存地址)的 指针

    例如,假设我们有

    char a = 'a';
    char *b = &a;
    

    从图形上看是这样的:

    +-----+ 变量 a:| '一个' | +-----+ ^ | +------------------------+ 变量 b:|变量 a 的地址 | +------------------------+

    变量b指向变量a

    如果打印这两种类型的尺寸,差异应该是相当明显的:

    printf("sizeof(char) = %zu\n", sizeof(char));
    printf("sizeof(char *) = %zu\n", sizeof(char *));
    

    第一行应该说char 的大小为1(顺便说一下,在C 规范中指定始终为1)。指针的大小应该是 4(在 32 位系统上)或 8(在 64 位系统上)。

    【讨论】:

      【解决方案3】:

      @SouravGhosh 给你一个很好的答案,这里有一个建议:

      不要使用像plblFileName这样的全局变量:

      char on_btn_Convert_clicked()
      {
         //define variables
         char *hello;
      
         hello = "hello!";
      
         gtk_label_set_text(GTK_LABEL(plblFileName), hello);
         return 0;
      }
      

      为此信号使用正确的原型 ("clicked")

      void on_btn_Convert_clicked(GtkButton *button, gpointer user_data)
      {
         //define variables
         char *hello;
      
         hello = "hello!";
      
         gtk_label_set_text(GTK_LABEL(user_data), hello);
      }
      

      并连接通过标签的信号:

      g_signal_connect(G_OBJECT(pbtnConvert), "clicked", 
                       G_CALLBACK(on_btn_Convert_clicked), plblFileName);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-24
        • 2010-09-18
        相关资源
        最近更新 更多