#1
  1. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2013
    Posts
    109
    Rep Power
    3

    String copy: using strcpy() and a pointer


    I want to take a pre-declared string and copy it, using strcpy function. But if i pass strcpy() a pointer, into which it copies the new string, how will i tell the compiler that the destination pointer i passed to strcpy is supposed to point to a full string and not only a char?
    Code:
        char *array[2]={"hello", "ok"};
    
    
        
        char *ptr; <------Program crashes, probably that's the reason ??
    
    
        
        strcpy(ptr, array[1]); <----Shouldn't he take ptr as a pointer to a STRING as well as a pointer to a single char ?
    
    
        printf("%s", ptr); /*CRASH*/
    I would like to do this using pointers only.
  2. #2
  3. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,179
    Rep Power
    2222
    Originally Posted by C learner
    I want to take a pre-declared string and copy it, using strcpy function. But if i pass strcpy() a pointer, into which it copies the new string, how will i tell the compiler that the destination pointer i passed to strcpy is supposed to point to a full string and not only a char?
    You are already. A char* points to a single char as well as to an array of char, AKA "a string". It's equivalent.

    Originally Posted by C learner
    Code:
        char *ptr; <------Program crashes, probably that's the reason ??
    
    
        
        strcpy(ptr, array[1]); <----Shouldn't he take ptr as a pointer to a STRING as well as a pointer to a single char ?
    
    
        printf("%s", ptr); /*CRASH*/
    Actually, I would think that the crash would have happened in the strcpy because of the access violation, AKA "SEGFAULT".

    ptr is an uninitialized pointer. I've seen MinGW gcc throw warnings about using an uninitialized variable, so I would think that you should have gotten warnings on that.

    If declared locally, an uninitialized pointer contains garbage, which means that it could be pointing anywhere. Since most memory addresses in your system do not belong to your process, there is a large probability that that garbage address points to memory that does not belong to your process. The OS has a vested interest in protecting itself and all other user processes from any user process accessing memory that does not belong to it. Such a violation is called a number of things, including "access violation", "protection violation", and, for historical purposes from 16-bit segmented-memory systems, "segmentation fault" (AKA "SEGFAULT"). Such a violation is grounds for immediate termination with extreme prejudice, AKA "your program crashes".

    Even if out of blind bad luck that garbage address just happens to fall in memory that you own, you can still get an access violation. That memory you own includes your program code and literals, both of which are in a block of memory deemed read-only. If you try to write to a read-only location, then you will be committing an access violation and you will be terminated. And if you have even worse bad luck, it will point to read-write memory that you own and cause you no end of serious problems. Remember, if you're lucky, your program will crash, but if you're unlucky then it will just diddle random data and produce really weird and "inexplicable" results.

    If declared globally, an uninitialized pointer will contain address 0x00000000, which is at the very start of memory space and which is a common value for NULL. Traditionally in Intel boxes, that location marks the start of the Interrupt Vector Table (IVT) which most definitely belongs to the OS and which the OS will most definitely protect against all user attempts to access it.

    To make your program work correctly, you need to point ptr to read-write memory that belongs to your process and which can be safely written to, which includes being large enough for the string plus the null-terminator. You can accomplish that either by declaring ptr as a char array, by calling malloc or calloc to allocate memory to ptr, or by doing the copy with a function that will do that for you, such as strdup().
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2013
    Posts
    109
    Rep Power
    3
    Thanks, very informative.

    I'll keep it in mind. :)

    The allocation solved the whole thing and it worked, no idea why i forgot about it.
  6. #4
  7. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,179
    Rep Power
    2222
    It seems that pointers appear to most students as something abstract and almost magical, whereas they are actually very firmly rooted in concrete reality. Every bit of data has to be stored somewhere and every memory location contains some value, even uninitialized variables. That means that every pointer, even the uninitialized ones, contains an address, even if it's just a random garbage address. If you always keep that in mind, you shouldn't go wrong.

    Myself, I started out training as an electronic computer systems repairman in the US Air Force, so I learned about logic circuits and memory and how the hardware works. So when I started working on my computer science degree, none of those "abstract" concepts of registers and memory were the least bit abstract to me. In my second semester I learned assembly programming, but in tech school I had already learned how a CPU fetches, decodes, and executes machine instructions so none of the "abstract" concepts of assembly were the least bit abstract to me. Part of assembly programming involves loading a value, which is the address of some data, into a register and then using that register to indirectly address that data as well as performing arithmetic on an address. Because of that experience, the concept of pointers and understanding what they do came naturally to me.

    My point with that history is to emphasize that everything you do in programming is based firmly on operations that are performed by the hardware. An experienced C programmer always keeps in mind how the hardware implements what he's writing (eg, what pointers are doing, how the number of bits and the format of the data affects the results). There is very little that is truly abstract or arbitrary.
  8. #5
  9. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2013
    Posts
    109
    Rep Power
    3
    That's EXACTLY what i was having in mind today: if only i knew what was going on inside the hardware, perhaps my program wouldv'e been written a bit different. I haven't studied hardware, yet.

    I'm going to study Electronics & Computer engineering soon. Hopefully it will give me a wider scope on what is really going on. :cool: Just thought to begin with C beforehand.
  10. #6
  11. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,179
    Rep Power
    2222
    I would recommend then that you also start reading up on assembly programming. That will get you down to the level of individual instructions, CPU registers, low-level addressing modes, memory access, etc. Keep in mind that every family of CPU/microprocessor has a different instruction set and different organization, so each one has its own assembly language. Still, the advantage of learning one is that you also learn the concepts that the others are based on.

    I would recommend studying Intel 80x86 assembly, since that is what your computer is based on.

    One of the best books on this subject is also one of the most dated: SAMS' 8080A Bug Book. In the late 1970's, Intel's 8080A microprocessor was a favorite among hobbyists and manufacturers: the 8080A and support chips were sold in Radio Shack and it was used in their home computer, the Tandy Radio Shack 80 (TRS-80, known affectionately as "the Trash-80"). The 8080A formed the basis for the later 8086 which was used in the IBM PC and whose many generations are still used for building both Windows and Linux boxes. The 8080A Bug Book examined the chips, how to incorporate them into a design, the clocking signals for accessing memory or I/O ports, the registers and their usage, the instruction set, etc. But all that is now considered old and arcane knowledge, though if you get involved in designing computer hardware then those concepts will still be used.

    PS
    I should probably also refer you to a textbook for a class I took a decade ago: Assembly Language Programming for the IBM PC Family 3rd ed. by William B. Jones, Scott Jones Publishers, 2001. Besides teaching the basics, it also covers how to program higher-level-language control structures (eg, if-then-else, while loops, for loops, switch) and function and procedure calls for C and for Pascal. We used Microsoft's MASM assembler for the class.
    Last edited by dwise1_aol; August 5th, 2013 at 03:29 PM.
  12. #7
  13. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2013
    Posts
    109
    Rep Power
    3
    Wow, it sounds really good. :)

    Probably will make C a lot clearer, i'll look for it.
  14. #8
  15. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,179
    Rep Power
    2222
    Well, you will eventually have to work with assembly code, so if nothing else it'll give you a head start. And as a side benefit, it can help you understand more of what's really going on.
  16. #9
  17. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2013
    Posts
    35
    Rep Power
    2
    char *array[2]={"hello", "ok"};



    char *ptr;



    strcpy(ptr, array[1]);


    printf("%s", *ptr); //just use a *

IMN logo majestic logo threadwatch logo seochat tools logo