whats wrong in following code cpp

Discussion in 'Programmer's Corner' started by ep.hobbyiest, Mar 30, 2016.

  1. ep.hobbyiest

    Thread Starter Member

    Aug 26, 2014
    91
    0
    Hi,

    Following is my simple code. but it is not giving expected output. here is my code.
    Code (C):
    1.  
    2. #include<iostream>
    3. #include<stdio.h>
    4. using namespace std;
    5.  
    6. typedef unsigned char Ch;
    7.  
    8. typedef struct abc_s
    9. {
    10.     int f;
    11.     char x;
    12. }abc_t;
    13.  
    14. int main()
    15. {
    16.     Ch a,b,c,d;
    17.     abc_t stru;
    18.     char *arr;
    19.     stru.f = 20;
    20.     stru.x = 'H';
    21.     a = 'O';
    22.     b = 'B';
    23.     c = 'B';
    24.     d = '!';
    25.     cout<<"Start"<<endl;
    26.     snprintf(arr,6,"%c%c%c%c%c",stru.x,a,b,c,d);
    27.     cout<<arr<<endl;
    28. }
    29.  
    30.  

    expected output is
    Code (Text):
    1.  
    2. Start
    3. HOBB!
    4.  
    but curretly it is coming as
    Code (Text):
    1.  
    2. Start
    3.  
     
    Last edited by a moderator: Apr 16, 2016
  2. WBahn

    Moderator

    Mar 31, 2012
    17,777
    4,805
    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.
     
  3. ep.hobbyiest

    Thread Starter Member

    Aug 26, 2014
    91
    0
    so u meant to say i should allocate memory for this array?
    can you give some reference for the same
     
  4. WBahn

    Moderator

    Mar 31, 2012
    17,777
    4,805
    Uh, yeah -- allocating memory for an array before you use it is generally considered a good thing to do.

    http://bfy.tw/50fd
     
    ep.hobbyiest likes this.
  5. Brownout

    Well-Known Member

    Jan 10, 2012
    2,375
    998
    Code (Text):
    1.  
    2. char *arr = "      ";//reserves memory for pointer "arra"
    3.  
    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: Apr 24, 2016
  6. WBahn

    Moderator

    Mar 31, 2012
    17,777
    4,805
    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 (Text):
    1.  
    2. char *fred = "Hello World";
    3. char *sue = "World";
    4.  
    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.
     
  7. Brownout

    Well-Known Member

    Jan 10, 2012
    2,375
    998
    Always worked for me. Worth a try at least.
     
  8. WBahn

    Moderator

    Mar 31, 2012
    17,777
    4,805
    I guess -- provided writing code that might work today and not work next week is worth a try. Personally, I don't think writing such code is worth anything.
     
  9. Brownout

    Well-Known Member

    Jan 10, 2012
    2,375
    998
    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.
     
  10. WBahn

    Moderator

    Mar 31, 2012
    17,777
    4,805
    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.
     
  11. Brownout

    Well-Known Member

    Jan 10, 2012
    2,375
    998
    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.
     
  12. Tesla23

    Active Member

    May 10, 2009
    318
    67
  13. Brownout

    Well-Known Member

    Jan 10, 2012
    2,375
    998
    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
     
  14. WBahn

    Moderator

    Mar 31, 2012
    17,777
    4,805
    I'd recommend rethinking the issue again.

    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).
     
  15. Brownout

    Well-Known Member

    Jan 10, 2012
    2,375
    998
    Yeah, we straightened all that out in posts #12 and #13.
     
  16. WBahn

    Moderator

    Mar 31, 2012
    17,777
    4,805
    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.
     
  17. WBahn

    Moderator

    Mar 31, 2012
    17,777
    4,805
    Okay -- I'm just getting caught up with the thread. Glad to see you came around.
     
  18. Tesla23

    Active Member

    May 10, 2009
    318
    67
  19. John P

    AAC Fanatic!

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

    Code (Text):
    1.  
    2. struct abc_s                         // No typedef
    3. {
    4.     int f;
    5.     char x;
    6. }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().
    7.  
    8. int main()
    9. {
    10.     Ch a,b,c,d;
    11.     //abc_t stru;                         Not needed
    12.     char *arr;
    13.     //stru.f = 20;
    14.     //stru.x = 'H';
    15.     abc_t.f = 20;                       // Load the elements of abc_t
    16.     abc_t.x = 'H';
    17.     a = 'O';
    18.     b = 'B';
    19.     c = 'B';
    20.     d = '!';
    21.     cout<<"Start"<<endl;
    22.     [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);
    23. [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
    24.     cout<<arr<<endl;
    25. }
    26.  
     
Loading...