为什么指针起作用而不是这段代码中的普通变量?
Why does a pointer work and not a normal variable in this code?
在我的下面的代码中,我得到了以下警告:
In function ‘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 变量的版本相比有效吗?
因为在你代码的第一部分
char hello;
hello = "hello!";
是错误的,因为您的编译器已经警告过您。
A string literal 形式 "Hello!"
returns 指向第一个元素的指针,即字符串中第一个元素的地址,不能存储到 char
。你需要一个 char *
来保持它。
或者,您可以使用数组 char hello[] = "hello!";
。这将创建一个数组并使用字符串文字 "hello!" 初始化数组,这也应该可以正常工作,但简单的(标量)char
无论如何都不起作用。
像"hello"
这样的常量字符串文字实际上是一个包含六个字符的数组('h'
、'e'
、'l'
、'l'
、'o'
和终止符 '[=23=]'
)。当您使用它时,它可以衰减到指向其第一个元素的指针。
这就像拥有一个实际的数组:
char hello_array[6] = { 'h', 'e', 'l', 'l', 'o', '[=10=]' };
然后将其分配给一个指针,如
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;
在图形上可以这样看:
+-----+
The variable a: | 'a' |
+-----+
^
|
+-----------------------+
The variable b: | Address of variable 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 位系统上)。
@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);
在我的下面的代码中,我得到了以下警告:
In function ‘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 变量的版本相比有效吗?
因为在你代码的第一部分
char hello;
hello = "hello!";
是错误的,因为您的编译器已经警告过您。
A string literal 形式 "Hello!"
returns 指向第一个元素的指针,即字符串中第一个元素的地址,不能存储到 char
。你需要一个 char *
来保持它。
或者,您可以使用数组 char hello[] = "hello!";
。这将创建一个数组并使用字符串文字 "hello!" 初始化数组,这也应该可以正常工作,但简单的(标量)char
无论如何都不起作用。
像"hello"
这样的常量字符串文字实际上是一个包含六个字符的数组('h'
、'e'
、'l'
、'l'
、'o'
和终止符 '[=23=]'
)。当您使用它时,它可以衰减到指向其第一个元素的指针。
这就像拥有一个实际的数组:
char hello_array[6] = { 'h', 'e', 'l', 'l', 'o', '[=10=]' };
然后将其分配给一个指针,如
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;
在图形上可以这样看:
+-----+ The variable a: | 'a' | +-----+ ^ | +-----------------------+ The variable b: | Address of variable 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 位系统上)。
@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);