whats wrong in following code cpp

Thread Starter

ep.hobbyiest

Joined Aug 26, 2014
147
Hi,

Following is my simple code. but it is not giving expected output. here is my code.
C:
#include<iostream>
#include<stdio.h>
using namespace std;

typedef unsigned char Ch;

typedef struct abc_s
{
    int f;
    char x;
}abc_t;

int main()
{
    Ch a,b,c,d;
    abc_t stru;
    char *arr;
    stru.f = 20;
    stru.x = 'H';
    a = 'O';
    b = 'B';
    c = 'B';
    d = '!';
    cout<<"Start"<<endl;
    snprintf(arr,6,"%c%c%c%c%c",stru.x,a,b,c,d);
    cout<<arr<<endl;
}

expected output is
Code:
Start
HOBB!
but curretly it is coming as
Code:
Start
 
Last edited by a moderator:

WBahn

Joined Mar 31, 2012
25,062
You are not initializing arr. You have declared it to be a pointer to char, but you never allocate memory or make arr actually point to anything. So it is unitialized and is pointing to some random location in memory. Dereferencing uninitialized pointers generally invokes undefined behavior -- there be many demons in those waters.
 

Brownout

Joined Jan 10, 2012
2,390
Code:
char *arr = "      ";//reserves memory for pointer "arra"
Edit: The comment editor removed my many spaces between the double quotes.

MOD EDIT: Placed code in CODE tags to preserve spaces.
 
Last edited by a moderator:

WBahn

Joined Mar 31, 2012
25,062
Code:
char *arr = "      ";//reserves memory for pointer "arra"
This is risky and on many platforms won't work (at least not as intended). The string that the pointer is set to is a string literal and, hence, is often within the body of the code. That, by itself, can make it so that the variable arr can't be set to it (think Harvard architecture). Even if it can, on such an architecture your code probably can't write to it. If you are on an architecture where this isn't a problem, changing it puts you in the realm of self-modifying code.

I found this out the hard way a couple decades ago when I had something like (junk example to illustrate what I did -- this is not the actual code)

Code:
char *fred = "Hello World";
char *sue = "World";
I then changed sue so that it held "Bob" and when I printed out fred it printed "Hello Bob". This is because the compiler recognized that the second string was a suffix of the first and so, in the code body, it only stored the first string literal and simply pointed sue to the proper place within it. It was a subtle logic flaw that took me several days to figure out (the fact that I had been programming in C for a short time and had no idea about the internals of how high-level programs work didn't help).

I think (don't recall for sure) that I was using Borland's TurboC compiler. It was back in the Win3.1 days and the RAM memory was something like 8 MB, so compilers played a lot of tricks to optimize memory use.
 

Brownout

Joined Jan 10, 2012
2,390
Never had code that worked one week and not the next. If the OP has covered dynamic memory allocation, he can try this

char * myChar = malloc(10*sizeof(char));

Just remember to free the memory when done with it.
 

WBahn

Joined Mar 31, 2012
25,062
Never had code that worked one week and not the next. If the OP has covered dynamic memory allocation, he can try this

char * myChar = malloc(10*sizeof(char));

Just remember to free the memory when done with it.
I'm referring to code that works using one compiler (today) but doesn't work under a different compiler or a different version of a compiler (next week). Related is code that works on your machine but then you send it to someone (a collaborator or a customer or make it available for people to download) and it doesn't work when compiled using THEIR compiler.

Dynamically allocating memory is by far the safer way and, as you pointed out, it should be freed when done with it.
 

Brownout

Joined Jan 10, 2012
2,390
Deleated my post because I re-thought this issue. Actually, there is no reason this code wouldn't run on any platform if compiled by a compliant compiler. Although the variable is initialized, it's still a variable, and as such, would always be writable, at least from the perspective of a complaint compiler. Maybe not the best or most safe, but should always work nevertheless.
 

Brownout

Joined Jan 10, 2012
2,390

WBahn

Joined Mar 31, 2012
25,062
Deleated my post because I re-thought this issue.
I'd recommend rethinking the issue again.

Actually, there is no reason this code wouldn't run on any platform if compiled by a compliant compiler. Although the variable is initialized, it's still a variable, and as such, would always be writable, at least from the perspective of a complaint compiler. Maybe not the best or most safe, but should always work nevertheless.
Really? Let's see what is required of a compliant compiler:

From Section 6.4.5 of the C Standard (C99) on String Literals.

"It is unspecified whether these arrays are distinct provided their elements have the appropriate values. If the program attempts to modify such an array, the behavior is
undefined."

The behavior of the compiler as I described back in Post #6 was completely in compliance with the standard (C88 at the time).
 

WBahn

Joined Mar 31, 2012
25,062
The link shows the correct way:

char pMyChar[] = "blah blah blah" Now the array name "pMyChar" without the brackets may be used as a pointer as in
strcpy(pMyChar, "some string") or alternatively, you may simply declare "char pMyChar[10]" to allocate a 10 character variable space.

Been so long I forgot about char arrays
Using

char pMyChar[] = "blah blah blah";

is perfectly correct and compliant. The semantics are very well defined. The unspecified size of the array is implicitly determined by the compiler to be just long enough to store the string (including the terminating NUL character) and code is inserted to initialize the elements of the array to the corresponding elements of the string literal. The array may or may not be static, but the string literal itself IS static and is stored elsewhere (generally within the body of the code) in an implementation-dependent way.

Using

char *pMyChar = "blah blah blah";

invokes undefined behavior.

Attempting to modify a string literal may or may not work and may appear to work in some instances and not in others and may appear to work on one platform and not on another. String literals are often physically stored within the body of the code, are not guaranteed to be distinct from other string literals, and are not guaranteed to be writable.
 

John P

Joined Oct 14, 2008
1,785
I don't think that structure is being properly handled. I'd do it like this:

Code:
struct abc_s                         // No typedef
{
    int f;
    char x;
}abc_t;                                  // Now you've defined a kind of structure 'abc_s' and created one named 'abc_t'. It's global, not limited to main().

int main()
{
    Ch a,b,c,d;
    //abc_t stru;                         Not needed
    char *arr;
    //stru.f = 20;
    //stru.x = 'H';
    abc_t.f = 20;                       // Load the elements of abc_t
    abc_t.x = 'H';
    a = 'O';
    b = 'B';
    c = 'B';
    d = '!';
    cout<<"Start"<<endl;
    [URL='http://www.opengroup.org/onlinepubs/009695399/functions/snprintf.html']//snprintf[/URL](arr,6,"%c%c%c%c%c",stru.x,a,b,c,d);
[URL='http://www.opengroup.org/onlinepubs/009695399/functions/snprintf.html']    snprintf[/URL](arr,6,"%c%c%c%c%c",abc_t.x,a,b,c,d);                                         // Maybe that arr thing will work, but note abc_t.x
    cout<<arr<<endl;
}
 
Top