In my below code I get the following warnings went built:
In function ‘on_btn_Convert_clicked’:|
warning: assignment makes integer from pointer without a cast [enabled by default]|
warning:passing argument 2 of ‘gtk_label_set_text’ makes pointer from integer without a cast [enabled by default]|
||=== Build finished: 0 error(s), 2 warning(s) (0 minute(s), 1 second(s)) ===|
If i run the program as is it will open the GUI but the button in question will cause a segmentation fault when pressed and crash the program.
#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 );
}
However, if I make the variable 'hello' a pointer then the errors go away and everything works.
Like this:
char on_btn_Convert_clicked()
{
//define variables
char *hello;
hello = "hello!";
gtk_label_set_text(GTK_LABEL(plblFileName), hello);
return 0;
}
I dont understand how a pointer, the object that just points to a place in memory, can be made equal to "hello" and still work like this?
Can anyone explain to me why the 'char hello' variable needs to be a pointer (*) and cant just be a string or 'char[]'?
Finally, can you summarize why this is working versus the version with a normal char variable?
A constant string literal like "hello"
is actually an array of six characters ('h'
, 'e'
, 'l'
, 'l'
, 'o'
and the terminator '\0'
). When you use it, it can decay to a pointer to its first element.
It's like having an actual array:
char hello_array[6] = { 'h', 'e', 'l', 'l', 'o', '\0' };
and then assigning it to a pointer like
char *hello = &hello_array[0];
The above is what is basically what is happening when you do
char *hello = "hello";
When you have
char hello = "hello";
it's like doing
char hello = &hello_array[0];
That simply doesn't work. It's the same when calling the function, it expects an argument of type char *
and you pass an argument of type char
. Those two types are not the same by a long stretch.
Another way of explaining it might be for you to think something like this: A variable is a place to store a value. When you have a variable of type char
you can store a single character. When you have a pointer to a character you can store exactly that, a pointer to a character (actually a memory address).
For example, lets say we have
char a = 'a';
char *b = &a;
Somewhat graphically it could be seen like this:
+-----+ The variable a: | 'a' | +-----+ ^ | +-----------------------+ The variable b: | Address of variable a | +-----------------------+
The variable b
points to variable a
.
The difference should be quite obvious if you print the sizes of the two types:
printf("sizeof(char) = %zu\n", sizeof(char));
printf("sizeof(char *) = %zu\n", sizeof(char *));
The first line should say that the size of char
is 1 (it's specified in the C specification to always be 1
by the way). The size of the pointer should be either 4 (on a 32-bit system) or 8 (on a 64-bit system).