Friday, January 28, 2011

Naive prime finder

I'm going to try to tackle a few of the first Euler Project tasks. Some of the first ones involve finding prime numbers, so I want to make a generic "is this number prime?" function to handle that.

The basic definition of a prime number is a number that only has two divisors - one and itself - that fit right (no remainder).

Ok well, that's what mod (%) is for. Here is my first run at a program that finds the prime numbers in 1 to 20. I'll explain why this is a naive implementation in a second:



This program is a pretty brute force counter of how many times (index % i) returns 0 (meaning no remainder). Index is the number we want to test, and i loops from 1 to index testing (index % i).

I call this a naive implementation because I know better than to loop through every number up to the index but I want to make it basically work before I "optimize" it.

*EDIT*

I pretty much wrote this in one shot, and it didn't work the first time. Everything was coming up prime. Turned out I fumbled out a = instead of == when checking to see if divisors was 2. "something = something else" is a "true" statement regardless of what both are. "something == something else" is a condition that is true if equal, false if not.

Thursday, January 27, 2011

int division

int i = 11/2;

printf("i is %d\n",i);

Result is "i is 5".

I expected this, but just making sure. Changing %d to %f makes it print "i is 0.000000", which I also expected since any int you're trying to print as a float comes out as 0 like that. There's probably a reason for this, but I'd have not guessed it not knowing any better (meaning I had tried it before).

Mleh

Busy busy at work. This weekend is booked solid with me not being at the apartment. I'm worried I won't get my hands on a keyboard for two days straight which is going to probably lead to me forgetting everything I've learned.

100th post. Hooray.

But for real, I make the biggest leaps in knowledge when I code every day, and I haven't done anything significant since Sunday.

Tuesday, January 25, 2011

helping hand

I finally had the opportunity to tell someone in /r/learnprogramming something I wish I had known last summer.

http://www.reddit.com/r/learnprogramming/comments/f8zbc/need_help_with_kr_exercise/c1e7q2g

I'm seriously considering writing up a "Learning C with K&R" post full of things I wish I had known six months ago.

A looming problem

It seems like GTK callback functions (functions that are run in response to events like buttons being pressed) have very specific prototypes, and the last parameter is always a gpointer to user data.

But here's the problem.

Lets say I need to pass a handful of variables to a callback function. Two integers and an array. I only have ONE space (my gpointer) for this in my callback function prototype.

The only solution I've found online is to "pack" my variables into a structure and then pass the address of the structure to my callback function, but this seems like a really roundabout way of doing it. PLUS it forces you to gear the internal workings of a program around the GUI library you want to use. Is this normal?

I mean say I have an old CLI based program that I want to make a GUI for and this program is just a collection of functions with a whole mess of parameters required. I'd have to redesign the entire variable flow just to crowbar in a GUI. That seems crude!

In my last program (exercise 2-1) I was forced to declare my character arrays outside of main() because I didn't know any way to pass them to my callback function otherwise. My gpointer was taken up by label, anyways. What if I wanted to change the text on two labels, called label1 and label2? How do I pass the second one? Am I allowed to assign another callback to deal with label2? Maybe if I make my callback function a gboolean that returns FALSE to indicate that I didn't finish dealing with the event.

Ok - tonight's homework is to try that. I'll make two callbacks in response to 1 event and return false on the first callback and true on the second. Maybe that will work.

I'll keep an eye out on how to gracefully deal with a plethora of variables needing to be passed to a callback function.

useful to note

if (g_ascii_strcasecmp (gtk_window_get_title(GTK_WINDOW (window)),text2) == 0

g_ascii_strcasecmp returns 0 if the two arguments (each a char*) are the same. So in my function I'm asking "hey are you already text2? Oh g_ascii_strcasecmp returned 0 so you are text2? Ok then you're text1 now.

WHY it's not doing this consistently is screwing with my head. What I might do is be really assertive and do that condition on both the window and the label. It's redundant, but it might alter the behavior.

Exercise 2-1 in the GTK book



The exercise was to make a window with a title and a label (the text in the window). When you press a keyboard key the text in the window title and label should swap.

Didn't take too long to figure out how to get a property of a widget (the title text status is how I determine which way to swap things), and there is a GDK function for testing if strings are identical, or if the first is larger than the second, or vice versa. Also wasn't too hard to find.

Here's the problem - it doesn't always work. Sometimes I'll press a button and both texts will swap. Sometimes only the label will change (making both texts the same), and very rarely only the window title will change. I need to run this on my Windows box to see if the behavior is the same. If it is then I'll do some searching. If I had more time this morning I'd rewrite the swap text function just to see if that would alter the behavior.

I'm happy with this because I started from scratch and only had to reference the book or the API doc for new stuff that the book hadn't covered yet, like getting a widget attribute. That's what this book is good about. It says "do this exercise but be warned that you'll need functions regarding getting attributes we haven't covered yet and you need to look in the API docs to get that function".

The next exercise expands this program by using a button you click on instead of a keypress. Maybe tonight or tomorrow morning I'll work on that. Having two hours to myself in the morning (since Ana gets up so early and I wind up waking up, too) is a blast. Crashing at 3:30pm isn't, however.

*EDIT*

Also, I've started standardising how I use spaces. Spaces after commas in function calls, spaces in between function name and parameters list.
So is any function passed as an argument a "callback function"?

Every time I see "callback function" mentioned in a tutorial or my book it has to do with function pointers and then passing the addresses as arguments. In GTK I'm not declaring my functions as anything other than vanilla function but I'm passing them as arguments.

Something on the to do list is figuring out how qsort works. Qsort requires an address to a function.

*EDIT*

I just realized that in GTK my g_signal_connect functions look like this:

g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (killwindow), NULL);

My callback function killwindow() isn't a function pointer, but G_CALLBACK(killwindow) is casting my killwindow() function to be void (*killwindow)(...).

http://library.gnome.org/devel/gobject/unstable/gobject-Closures.html#GCallback

Monday, January 24, 2011

looking ahead

The "Timestamp" program is what got me started on this journey, and it looks like I'm nearing that point of being able to complete it.

I'm on the path to being able to create a UI with buttons going down vertically, with one button on the bottom to "commit" the selected above buttons (each called something different for each thing you want to mark as happened). The last piece of the puzzle that I don't see how to solve is a storage solution. Let's say I have pressed the button for "breakfast" and "had coffee". When I hit "commit" I need to record an entry for "breakfast" and an entry for "coffee" to somewhere. Each entry will have an ID (the name, I guess) and a time.

I first thought of just dumping to a text file. Why not? It's the usual newbie solution to data storage.

The second thing I considered is maybe a SQL database. There are no shortages of how-tos online for this.

The third option that I can't shake is using Twitter as storage. Why couldn't I have an account that consisted of search-able tags that would (by means of how Twitter works anyways) have a time and date associated with it? When I hit "commit" the program would scan through every button and on finding one that was enabled it would submit a Twitter entry then move on to the next until the list was finished.

I did a quick search of C libraries for Twitter, but I'm coming up empty handed. Web stuff is tricky uses acronyms I'm not overly familiar with.

Anyways, I like this idea.
http://i.imgur.com/Y55lK.jpg

I have this "kitchen sink" program I've been adding stuff to as I learn GTK. It's a bit fast and sloppy because it's just fussing about with the stuff I've learned to see how much I can abuse it.

Once I learned how to initialize and add widgets, I wanted to see if an array of widgets was acceptable, and it seems that it is. I can even loop through the array and initialize/add widgets in the loop. "This is label 1" to "this is label 5" were added like that. If you press a keyboard key the window title text and "Press A Button" change to something else (which was the hard fought battle described in my last post).

I wanted it to change based off mouse clicks, but it seems only buttons emit that kind of signal.

Sunday, January 23, 2011

Today's Lesson

Today's lessons are:

A) Not all widgets are created equal.
B) Different signals/events require different callback function prototypes to handle them properly
C) READ THE DAMNED API DOCS

So here was my problem. I assumed that every callback function would have the same prototype:

function(GtkWidget*,gpointer)

This is not true. I was trying to act on a "button_press_event" which required:

function(GtkWidget*,GdkEvent*,gpointer)

And you know what? The API was blasting this in my face the entire time:

http://library.gnome.org/devel/gtk/stable/GtkWidget.html#GtkWidget-button-press-event

The scary thing is that the "destroy" event has the same prototype but my particular callback function didn't care about the values passed to it, so no problems were had even though I left something out.

I guess there isn't a way to get the compiler to warn me?

*EDIT* The vast majority of my confusion was because I found a tutorial program that did something similar. Instead of a key press in a GtkWindow widget they were clicking on a GtkButton widget. The "clicked" signal has a different prototype that just happened to be the same as the "wrong" prototype I was using for the "destroy" event in my program, which made me think that it was correct and something else was going on.

I feel like I leveled up today.

*EDIT x2*
The program.

sprintf



Just testing my knowledge of sprintf and passing a character array. There is a point to this. I've spent the past few hours wailing away at a program that segfaults regardless of how I handle the variables. I've hit the end of a chapter in my GTK book and I wanted to make sure I understood a few things. The program I'm writing is supposed to be a window with some text in it, and the text should change to something else when you press a key (no buttons yet, just grabbing the "a key was pressed" event). For some reason I get a big fat crash/segfault when the function for changing the text happens. What kills me is that it's practically identical to a tutorial program online. I can even run that program just fine.

I'm furious over this.

"self describing" char pointer example



This program really drives home what's happening. Big ups to Matt for explaining this.

The output:

The string mainZ points to is Test123
The addy contained in mainZ is 004030BD
The addy OF mainZ is 0028FF0C

Now we call the function to alter mainZ

The string localZ points to is Ipsum Lorem
The addy contained in localZ in local function is 00403024
The addy OF localZ in local function is 0028FEF0

The string mainZ points to is Ipsum Lorem
The addy contained in mainZ is 00403024
The addy OF mainZ is 0028FF0C

So you can see here that the address of the char pointer variable mainZ (as in, where mainZ is) stays the same. Good. The address that mainZ points to is first 004030BD, and then it takes on the address contained in localZ, 00403024.

The most important thing I've learned (again, big ups to Matt) is that the idea that initialized space in memory that happens in a local function is NOT destroyed. It can get LOST if you don't let a pointer outside of the function know where it is, but it's not magically deleted. I'm still plowing through the books I have looking for something that explicitly states that. Everything I read always says rather plainly that data outside of a local function is not accessible. This is true for named variables (like localZ) it seems, but not for assigned spots in memory, like the address of where a string literal starts.

Hopefully I can just look at the program next time I get confused!

Saturday, January 22, 2011

string.h

I was pondering about character arrays again.

I know I can do this:

char char_array[50] = "hello there\0";

and I'll have myself a nice little array of characters with enough space for 50 characters.

But what if I don't know what I want in there at the time of declaring it? I can't say:

char_array = "hello there";
or
char_array[0] = "hello there";

or anything like that. The first statement is the same as saying &char_array[0], and the second is trying to cram an address of a string literal into the first element of the character array, which you can't do.

I had thought that intuitively this would work:

char_array = "hello there";

since I know that char_array is a shorthand way of saying &char_array[0], but the compiler complains about mixing types. Specifically trying to assign a character pointer to a char array. I wonder if there is a clever casting trick that would fix that.... more experimenting is needed.

ANYWAYS.

I was trying to think of a way to assign a string to a character array after the fact, and thankfully there is a oft-used header called string.h that has a whole ton of string operation functions.

The one I needed was strcpy(), which does just what it says.

strcpy(char_array, "hello there");

copies "hello there" into my character array. K&R goes into detail about how to make your own version of this function (most of the examples in the book replicate standard library functions).

So there you go. Nice to have libraries.

Friday, January 21, 2011

Hello world GTK



I'll be going over this later today. It's mostly easy to follow - the only confusing part is the existence of the delete_event function that returns FALSE. There are signals that the widgets emit that you can catch and do stuff with (like closing the window when the "X" on the top right is clicked) but BEFORE those signals are emitted the underlying system emits an event. So...if you catch and act on an event then no signal for that event is emitted.

There are two g_signal_connect calls - one for catching "destroy" and one for catching "delete_event". It's not obvious (well, maybe it is by the name) that "delete_event" happens first and would subsequently cause the "destroy" event if left alone.

My callback function for the event (again - events before signals) is confusingly called delete_event (thanks Andrew Krause) and this function is run first before the callback for the "destroy" signal. By returning FALSE in the destroy_event function I am saying "this callback function didn't really do anything important enough to block the subsequent signal that this event will cause".

In fact, changing it to TRUE makes the "X" do nothing! You have to kill the window in task manager.

So that's how you can have a "Do you really want to quit" dialog. If you want to quit then the function for the event returns FALSE and the event delete_event causes the widget to emit the "destroy" signal which runs the destroy callback function which proper kills the window.

All these signals, events, and functions having similar names makes me want to set a standard for how I write things out. Maybe signals/events in "" and every function has a () after it. Just for readability.

*EDIT*
Jeez, 4:30AM Chris is not coherent enough to make journal entries. Fixed a few incorrect statements.

Thursday, January 20, 2011

I have a really good idea for a project that could be done with my current (few chapters in) knowledge of GTK. It's work related (again) but it's something I could actually use.

I have this National Instruments USB DO device that I want to use to sent pulses to the digital input part of my system here. Specifically, digital words triggered by a strobe pulse. My company has an SDK for doing this (basically pass a number and it does all the hard work for you). I'd like to make a UI over that with buttons for each bit in the word (MSB->LSB) that can be toggled, and then have one more button to transmit that number. So, graphically it would be binary and then I'd pass the value (in decimal) to the SDK.

Why not just enter a number to transmit? Because I keep finding myself needing to test things bit by bit, and I want to learn how to create buttons and callback functions and whatever.

Each button would need to have a callback function that does two things: toggle the color of the button (default gray to green and vice-versa)as well as increment/decrement the sum of the buttons. So, the third bit would add/subtract 4 depending on the toggle state. This SHOULD be fairly simple.

Should be..........dotdotdot

Tuesday, January 18, 2011

huh

The newer GTK book is outdated, too. I was getting super confused by the book all but glossing over what I think is a really important concept in GTK - signals and callbacks. That's how every interactive thing works. You click/drag/etc and the widget emits a signal. There are specific calls to "catch" those signals and execute a function (as well as pass that function various things). Those functions are poorly explained in this book, and one variant of the function is used frequently and was never explained.

I look it up in the latest docs and the notes all but say "uhh yea this isn't super useful so don't worry about it unless you really need it".

-sigh-

Is this what being a "real" programmer is like?

Monday, January 17, 2011

adding on

I'm putting OpenCV on the list of things to get familiar with.

Hopefully 2011 will see a rat-controlled (via webcam tracking) VST plugin (or MIDI controller) that converts x-y coordinates to MIDI commands.

weekend

I spent a lot of my weekend making boxes appear. I wouldn't say I've learned much about the greater world of GUI programming - I was too busy going "WOO PRETTY BOXES".

Something unexpected did happen. I was confused with something the book didn't go into much detail about, so I looked up the call in the API docs themselves and figured out what I was missing. I didn't realize it until later but that was the first time I had done something like that.

Another thing that took me by surprise is how much I'm relying on GTK to "do the right thing" without me knowing the internals. There are a lot of layers and it's just not practical to know what each one below the calls I'm making does.

I was upset at first about accidentally buying an outdated book, but this book is so much better at filling in the gaps than the updated one. I'm sure I'll be writing about that later.

Sunday, January 16, 2011

Six months

As of yesterday I've been learning C for six months. Six months has taken me from futzing about in the console to starting to learn a GUI API. You know, I wonder what would happen if I counted the days I actually put time into it. If you assume that every day I studied and programmed I also wrote a journal post, then that's 82 days that I at least spent an hour or so on it.

That's not an accurate metric, however.

learnin

gcc -Wall -g GTKTest.c -o GTKTest `pkg-config --cflags gtk+-2.0` `pkg-config --libs gtk+-2.0`

The above is the terminal command to compile my first "hello world" style GTK program. I have seen stuff like this before with pkg-config on other tutorials but never knew what it meant. Thankfully this book is pretty good about explaining the unusual things that pop up - other web sites or books seem to assume that you know what all that means already. So, good on this book.

So the trick is that you want to make sure that all the header files for a GTK program can be seen by the compiler. Unfortunately there are tons of them. You include gtk.h in the program but that header has headers.

If you type in (sans quotes) "pkg-config -cflags gtk+-2.0" in the console you get this result:

-pthread -I/usr/include/gtk-2.0 -I/usr/lib/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/pango-1.0 -I/usr/include/gio-unix-2.0/ -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/libpng12

This is the stuff you gotta pass to the compiler, but since this is too much to reasonable type GCC has a neat little trick. Those tic mark things surrounding the pkg-config part of the GCC command will execute whatever is in between them and replace it with the result of that execution (the include pathways, in this case).

Pretty neat! I'm glad I'm getting some other info from this book.

I hit a bit of a problem when I didn't realise that those tics weren't apostrophes.

` is not equal to '

Saturday, January 15, 2011

notes

I've read through the first few chapters of both books. The older book is better about covering details of messaging and callbacks than the other, plus it talks about the underlying structure of the X Windows system. I don't think much of it is relevant anymore, however.

Since I can't get GTK+ to work like I want in Windows, I'll be spending more time on the netbook. The past month or so I've been doing stuff in Windows just as a convenience. Hooking up the netbook is cumbersome since I don't have a KVM. I don't even have the room for one. Too many wires and this desk is already a wreck.

Friday, January 14, 2011

bah

My books came in. One of them (I didn't realize) is old and is about GTK+ 1. The other book (thankfully the more well known and comprehensive one) is up to date and actually mentions how not backwards-compatible GTK+ 2 is. Not sure what to do with this other book. It wasn't expensive so I'm not hurt there.

reasons and ambitions

I'm learning C because it's widely used (from PCs to microcontrollers), all the programmers I respect started with C, and I still hold a grudge for flopping at learning it when I was younger. I think if I can gain a competency at this then I can do anything - particularly anything that I've failed at before, like mathematics higher than algebra and learning a foreign language.

C has its place, but I'm realizing I should eventually learn about (to some degree) more commonly used languages such as Java and web-oriented languages like Ruby. Most of the general programming stuff I see is about things I'm not even familiar with on a superficial level. Words like JSON, stuff on "rails", Canvas (or other aspects of HTML 5), CURL, etc. Not to mention databases, woof.

I have a book on Perl I never really dug into. Same with Python, but I think I got rid of that book. I used to have a PHP book (and actually did some PHP stuff I was proud of now that I think about it) but lost it.

There is a crapload of stuff to learn and I'm hoping that competency in C will give me the confidence to tackle any arbitrary platform or language.

My personal metrics for saying "I know C" I'm keeping somewhat secret for now. When I get close to that goal I'll pick up a book or some other resource on basic database usage. Most everything is stored in a SQL (or similar type) database and I figure I should have at least some knowledge of how to do this. I used mySQL a bit with the PHP app I wrote for the lab I used to work for, but it was a lot of copy/paste from the internet without really understanding what was going on.

Wednesday, January 12, 2011

project idea

My GTK+ books are on the way. I'll hopefully have them this week.

I have a good idea for a first project that will utilize my knowledge on reading in the files from work. The header of these files contain a user-inputted comment at the time of recording. I want to write a program that will let you open a file and change the comment after the fact in C and GTK+.

This seems like a good first project. I'll need to learn how to use the file opening dialog, and then have a text box that will let you change/add whatever comment is/isn't there, and then press a button that saves a new file.

The file manipulation aspect SHOULD be easy. The header is at the start of the file and is a fixed size. I'll read in the header, allow for the comment array in the structure to be changed, and then I'll write the header to a new file followed by the original file bytes starting at an offset of the header size. I wouldn't need to read in the original file - hopefully I can just stream from point A to point B...

Monday, January 10, 2011

a bit of back patting

I was able to answer a C programming related question for a customer at work. Someone is trying to read in one of our simpler file formats for conversion with Visual Basic and had some incorrect assumptions about the header structure size and how he would make this work in VB.

His first problem was that he thought integers are 2 bytes (they're 4) and doubles are 4 (they're 8). The second issue is that VB char is two bytes, so he's got his work cut out for him. He might be able to use the type byte (which is... 1 byte). I dutifully warned him about potential structure padding issues and provided useful Wikipedia links. He might not have problems but I have no way of knowing since I don't know squat about VB.

Sunday, January 9, 2011

void

I confirmed a hunch I had...

"Is that return statement necessary? What if the function was type void and I just did the operation? Further investigation is needed. I'm not sure why I even made it like that now..."

I changed my function to type void, returned nothing, and then just ran the function in main (without equating it to anything since it doesn't return anything). Since I passed it the memory address of my variable in main() it still worked.

Per my last post I think what I'm doing is a no-no, but meh for now.

Notes

K&R had something to say on my Question #1.

My Question: I thought that string literals had to be constant and couldn't be modified. This doesn't appear to be the case, but why?

K&R page 104 section 5.5:

char *pmessage = "now is the time";

...pmessage is a pointer, initialized to point to a string constant; the pointer may subsequently be modified to point elsewhere, but the result is undefined if you try to modify the string contents...


So that somewhat answers the question - nobody is going to stop you from doing it, but it's a bad idea. I've noticed that the phrase "undefined" in C literature usually means this.

This section (5.5) drives home that the following:

char amessage[] = "now is the time";

and

char *pmessage = "now is the time";

look the same but are not the same. amessage is an array just big enough to hold the sequence of characters (and terminating zero) that initializes it. pmessage is a pointer initialized to point to a string constant. I get confused easily because you can pass amessage somewhere (without the array index) and it means &amessage[0] which makes just amessage look like the pointer to a string, but it's just a pointer to the first element. I think I've written before about how I can't treat them the same. It's hard to internalize. It's even hard to know when something is a no-no when the compiler doesn't warn you!

Saturday, January 8, 2011

Analysis



I'll talk about the function MakeStringAlternate() first, as well as the variables local to main() called MakeString_Returned and mainW.

I have a pointer to a character variable called mainW, and I've assigned the string literal "Variable in Main\0" to this. I might discuss why I didn't go with the assignment char mainW[100] or similar later.

I have a function that will return a pointer to a character called MakeStringAlternate that takes a pointer to a char pointer as an argument with a local variable called localW. That is to say, it accepts as an argument the memory address of a char pointer. Inside this function I assign a different string to a dereferenced localW. Then I return a dereferenced localW.

So, what I have a done really then?

My goal was to alter a character string in one function (main) from another function (MakeStringAlternate). I can compile the program and it works, but why?

In main() I have the variable mainW that is a pointer to a character, and I have assigned a string to this. Specifically I think I assigned a string literal, if my reading is correct.

I want to alter mainW in the function MakeStringAlternate. To alter a variable local to one function from another, I need to give the other function the memory address of the variable. Since my variable is already a pointer I will be passing a pointer to a pointer - this is why the argument taken by MakeStringAlternate is (char **localW).

Ok, so I've passed the memory address of my variable local to main to the external function MakeStringAlternate. Inside MakeStringAlternate I make the following assignment:

*localW = "I have altered the variable in main\0";

This states that I am dereferencing localW - meaning I don't want to alter the memory address stored by localW, I want to alter what's AT the memory address contained in localW. At this memory address lives mainW in main() and I assign a new string literal.

What I'm most confused about is my return statement. If I'm returning a dereferenced pointer back to the variable I just altered, am I not saying:

address of mainW = address of mainW?

Is that return statement necessary? What if the function was type void and I just did the operation? Further investigation is needed. I'm not sure why I even made it like that now...

So, the BIG QUESTIONS.

1) I thought that string literals had to be constant and couldn't be modified. This doesn't appear to be the case, but why?

2) In the program I make a variable that just points to some memory with some text in it of a specific length. Then I say "you know what, replace that text with something longer!" and everything goes ok?! How did the compiler know not to put anything important in the stack right after my original declaration of the variable? Did I do a general no-no and get away with it?

3) I originally had the variables declared as "char mainW[100]" but abandoned it when the terminology got confusing. At least THIS would have made sense since I was allocating specific amounts of space! Would the compiler warn me if I was going over then?

Hopefully tomorrow I'll post about the other function MakeString, and why I don't understand why it works at all! Matt threw me some knowledge, but I don't understand the bits enough to really internalize things. Hopefully I can keep making these self-explaining programs as a reference.

wut?

I just noticed the program I wrote to test returning values from functions has a typo of sorts.

My function:

int MakeChar(char localY)
{
...
}

And in main() I have this:

char MakeChar_Returned = '0';

I then stated:

MakeChar_Returned = MakeChar(mainY);

Which essentially returned an integer value to a character variable!

I thought that wasn't allowed! I fixed it in the program, but this warrants further study. I think I remember that char can take numbers and when you use printf it just converts that number per the ASCII table. I'd have expected the compiler to at least warn me about mismatching return values and variables.

going back over things

I'm going to spend some time writing self-describing programs that will help me internalize some things as well as serve as a reminder if I forget.

Here is the first. It demonstrates what happens to local variables, and how to get the values you want via the "return" statement. I think I confused what "return" does before.

grumble

I'm frustrated with how blindsided by pointer stuff I have been getting. I'm not sure what to do next.

Wednesday, January 5, 2011

a reminder about strings and local variables



I was pondering to myself about local variables and how to pass values out of functions to main or other functions. While pondering I realized I wasn't sure how to pass a string. So, I wrote this program to prove I could do it.

string_generator takes a pointer to a character array as an argument, which is good because this is a memory address that won't get blown away once the function ends. While inside the function we pass some characters to the memory address. Here's where I get confused - it's one of those times where I know it's right but I don't know why it worked. I don't understand why I NEED to return the pointer back to itself (return str;).

To illustrate the point I'll add more code.



Here I have another function string_generator2. Again, I pass it the address of a string and pass characters to that address. When I try to print it out in the second printf I just get "(". I don't understand... isn't passing data to a memory address enough?

I kind of understand why the first function works. Printf wants a pointer to a character array and that's what the string_generator function delivers.

I thought that string2 was getting altered by string_generator2, but it doesn't seem to be.