Strange output problem

M

Materialised

Hi Everyone,

I am having a few issues while attempting to use Kevin Easton's base64
encryption algorythm. (See
http://groups.google.com/[email protected])

here is a sample program I am using to test the algorythm.

----- start main.c -----

#include <stdio.h>
#include "base64.h"

int main(void)
{
char string[5] = "hello";
int len;
char string2[10];
len = strlen(string);
printf("%s\n", string);
b64_encode(string2, string, len);
printf("%s\n", string2);

return 0;
}


----- end main.c -----

I compile the program using:

gcc base64.c main.c -o base

And when I run it I get the following output.
mick@codegurus $ ./base
hello?(????
aGVsbG/wBCjG7L+/AQ==??????(

Does anyone know where its going wrong?
 
P

Pedro Graca

I'll have a go! NEWBIE ANSWER -- probably full of errors too :)
#include <stdio.h>
#include "base64.h"

int main(void)
{
char string[5] = "hello";

string[0] = 'h'; /* this */
string[1] = 'e'; /* makes */
string[2] = 'l'; /* string */
string[3] = 'l'; /* 5 chars */
string[4] = 'o'; /* long! */
/* "hello" needs at least 6 chars: 'h', 'e', 'l', 'l', 'o', '\0' */

no more chars have been allocated

--> UB (undefined behaviour) ???

you are trying to copy '\0' to a place in memory you do not own.


You may want to let the compiler decide on the array size:
char string[] = "hello";

or specify enough size for your constants
char string[32] = "hello";
int len;
char string2[10];
len = strlen(string);

I think strlen() will go on after the final 'o' checking for the null
terminator which can be _anywhere_
printf("%s\n", string);

same thing here
b64_encode(string2, string, len);

and here
printf("%s\n", string2);

return 0;
}


----- end main.c -----

I compile the program using:

gcc base64.c main.c -o base

And when I run it I get the following output.
mick@codegurus $ ./base
hello?(????

Lucky you got a '\0' not very far away :)
 
M

Michael Fyles

Pedro Graca said:
Materialised said:
#include <stdio.h>
#include "base64.h"

int main(void)
{
char string[5] = "hello";

string[0] = 'h'; /* this */
string[1] = 'e'; /* makes */
string[2] = 'l'; /* string */
string[3] = 'l'; /* 5 chars */
string[4] = 'o'; /* long! */
/* "hello" needs at least 6 chars: 'h', 'e', 'l', 'l', 'o', '\0' */

no more chars have been allocated

--> UB (undefined behaviour) ???

Not undefined behaviour.
you are trying to copy '\0' to a place in memory you do not own.

It's actually a special case of character array
initialisation -- if there is not enough space for the
terminating null, it will not be assigned.
 
M

Mac

Pedro Graca said:
Materialised said:
#include <stdio.h>
#include "base64.h"

int main(void)
{
char string[5] = "hello";

string[0] = 'h'; /* this */
string[1] = 'e'; /* makes */
string[2] = 'l'; /* string */
string[3] = 'l'; /* 5 chars */
string[4] = 'o'; /* long! */
/* "hello" needs at least 6 chars: 'h', 'e', 'l', 'l', 'o', '\0' */

no more chars have been allocated

--> UB (undefined behaviour) ???

Not undefined behaviour.

Until you call a function which expects a C string. Without the
terminating NUL, it is not a string.
It's actually a special case of character array
initialisation -- if there is not enough space for the
terminating null, it will not be assigned.

--Mac
 
B

Bliss

Materialised said:
I am having a few issues while attempting to use Kevin Easton's base64
encryption algorythm.
here is a sample program I am using to test the algorythm.

----- start main.c -----

#include <stdio.h>
#include "base64.h"

int main(void)
{
char string[5] = "hello";
Bzzzt-----------------^^
Here is your problem. "hello" takes six chars (when you include the
terminating 0)
make that:
char string[] = "hello";
and let the compiler count the number of chars needed.
int len;
char string2[10];
len = strlen(string);
printf("%s\n", string);
b64_encode(string2, string, len);
printf("%s\n", string2);

return 0;
}


----- end main.c -----

I compile the program using:

gcc base64.c main.c -o base

And when I run it I get the following output.
mick@codegurus $ ./base
hello?(????
aGVsbG/wBCjG7L+/AQ==??????(

Does anyone know where its going wrong?
Yep you thought that "hello" was five chars long :)

Roger
 
L

Lew Pitcher

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Eric Sosman wrote:

| Thomas Stegen wrote:
|
|>Materialised wrote:
|>
|>>here is a sample program I am using to test the algorythm.
|>
|> ^^^^^^^^^
|>
|>I like this word :) Yeah, I got good algorythm.
|
|
| Algorhythm,
| Algomusic,
| Algorhythm,
| Who could ask for anything more?

"Algorythm" sounds like a method of birth control for programmers ;-)


- --

Lew Pitcher, IT Consultant, Enterprise Application Architecture
Enterprise Technology Solutions, TD Bank Financial Group

(Opinions expressed here are my own, not my employer's)
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (MingW32)

iD8DBQFAbb6LagVFX4UWr64RAqT6AKCXg0DmOffJRQ2PAvPyKzySzkTKSACeLz2U
zwnH0ydnwt66a8BMj+Tjrx0=
=6A5R
-----END PGP SIGNATURE-----
 
A

August Derleth

But OP's attempt to print it was, correct?

Indeed. printf() (and all other string-expecting C functions, whether or
not the Standard mentions them) expects a null-terminated string.
 
D

Dan Pop

In said:
Indeed. printf() (and all other string-expecting C functions, whether or
not the Standard mentions them) expects a null-terminated string.

Wrong!

fangorn:~/tmp 38> cat test.c
#include <stdio.h>

int main(void)
{
char word[5] = "hello";

printf("%.5s\n", word);
return 0;
}
fangorn:~/tmp 39> gcc test.c
fangorn:~/tmp 40> ./a.out
hello

And, to prove that it worked by design and not by accident:

s If no l length modifier is present, the argument shall
be a pointer to the initial element of an array of
character type. Characters from the array are
written up to (but not including) the terminating null
character. If the precision is specified, no more than
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
that many bytes are written. If the precision is not
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
specified or is greater than the size of the array,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
the array shall contain a null character.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The standard is usually very precise WRT when a null-terminated string
is actually expected and when any ordinary character array will do.
No need for bogus rules of thumb.

Dan
 
E

Eric Sosman

August said:
Indeed. printf() (and all other string-expecting C functions, whether or
not the Standard mentions them) expects a null-terminated string.

Nit-pick: If the "%s" conversion is used with a precision
(e.g. "%.10s" or "%.*s") the corresponding argument need only
point to the start of a character array, not necessarily zero-
terminated.

char hello[5] = "hello"; /* no terminator */
printf ("%s\n", hello); /* undefined behavior */
printf ("%.4s\n", hello); /* well-defined; prints "hell\n" */
 
D

Dan Pop

In said:
Dan Pop said:
char word[5] = "hello";
printf("%.5s\n", word);

Or, better yet,

printf( "%.*s\n", sizeof word, word );

Right?

Wrong. Undefined behaviour is never better than well defined behaviour.

Even if correctly done, your variant is ludicrous for my trivial example
and unlikely to be of much use in real life code, where the actual value
is seldom dictated by the size of the array (whose definition may not
even be in scope).

Dan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top