Memset and characters - c

I aim to copy source string to dest string. If i compile the following program:
#include <stdio.h>
int main(void) {
char dest[6];
char source[6];
strcpy(dest,source);
while (*dest) { printf("%c",*dest++); }
while (*source) {printf("%c",*source++); }
return 0;
}
I get a runtime error. I suspect it is because strcpy copies from source to destination till it encounters \0. It did not,however,encounter the null character and kept on copying from the buffer till the runtime error occurred. To solve this problem, i modified the code as follows:
#include <stdio.h>
int main(void) {
char dest[6];
char source[6];
memset(dest, '\0', 6*sizeof(dest)); //trying to set dest to '/0'
strcpy(dest,source);
while (*dest) { printf("%c",*dest++); }
while (*source) {printf("%c",*source++); }
return 0;
}
i get the following errors:
prog.c:11:38: error: lvalue required as increment operand
while (*dest) { printf("%c",*dest++); }
^
and
prog.c:11:38: error: lvalue required as increment operand
while (*dest) { printf("%c",*source++); }
^
Why does this happen?

For starters it is the source array that shall be zero terminated if you are going to copy it in another character arrays using the standard C function strcpy. So instead of this statement
memset(dest, '\0', 6*sizeof(dest));
you should at least write
memset(source, '\0', 6*sizeof(source));
^^^^^^ ^^^^^^^
However even this statement is wrong because it overwrites the memory allocated for the array. sizeof( source ) is already equal to 6 bytes as it is followed from the array declaration
char source[6];
Thus you have to write
memset(source, '\0', sizeof(source));
^^^^^^^^^^^^^
In fact there was enough to write either like
char source[6] = { '\0' };
or like
char source[6] = "";
or like
char source[6];
source[0] = '\0';
Arrays are non-modifiable lvalues. Thus you may not write for example the following way
while (*dest) { printf("%c",*dest++); }
Instead of this statement you could write
for ( char *p = dest; *p; ++p ) { printf("%c", *p); }
Take into account that nothing will be outputted because the array contains an empty string. You could initialize the source array with some non-empty string literal.

the following code cleanly compiles, and performs the desired operation.
The differences between the posted code and this are commented.
#include <stdio.h> // printf()
#include <string.h> // strcpy()
int main(void)
{
char dest[6]; // declared, containing garbage
char source[6] = "12345"; // declared, containing the string "12345\0"
strcpy(dest,source);
// now both arrays contain the string "12345\0"
// best to use a 'for()' statement for indexing through an array
for( size_t i=0; dest[i]; i++ ) { printf("%c", dest[i]); }
printf( "\n" ); // output the buffered data to the terminal
for( size_t i=0; source[i]; i++ ) { printf("%c", source[i]);}
printf( "\n" ); // output the buffered data to the terminal
// note, the following lines contain a precedence problem in
// the increment expressions and
// the address of an array declaration cannot be incremented
//while (*dest) { printf("%c",*dest++); }
//while (*source) {printf("%c",*source++); }
//return 0;// with modern C compilers,
// this line is not necessary in a 'main()' function
// when returning 0
} // end function: main

strcpy is not a safe function, prefer using strncpy.
The error is due to the fact that you try to increment the array, which is an rvalue (i.e. a constant, you can not put it to the left side of a sign =).
The common approach to iterate over an array is to use a pointer like so:
char *p = dest;
while (*p) { printf("%c",*p++); }

Related

How to assign a string to struct variable in C?

I am unable to figure out how to assign a string to a struct variable using only <stdio.h> header file.
The following code gives me an error and I am unable to fix it.
#include <stdio.h>
struct Student
{
char name[50];
};
int main()
{
struct Student s1;
printf("Enter studen's name:\n");
scanf("%s",s1.name);
printf("Name : \n",s1.name);
s1.name={"Hussain"};
printf("Name : \n",s1.name);
}
It gives the following error while compilation:
test.c: In function 'main':
test.c:12:12: error: expected expression before '{' token
s1.name={"Hussain"};
^
I have tried initializing it in the following way:
s1.name="Hussain";
But this doesn't work too.
I could avoid this by the use of pointers as follows:
#include <stdio.h>
struct Student
{
char *name;
};
int main()
{
struct Student s1;
printf("Enter studen's name:\n");
scanf("%s",s1.name);
printf("Name : %s\n",s1.name);
s1.name="Hussain";
printf("Name : %s\n",s1.name);
}
This code works perfectly fine with no errors.
But I want to know where exactly I am doing wrong with the array, which is making my code not work.
A char array (and arrays in general) can't be assigned a value directly, only initialized. To write a string into a char array, use strcpy.
strcpy(s1.name, "Hussain");
The latter code where the name member is a pointer works for the assignment because the pointer is assigned the start address of the start of the string constant. Also note that you can't (at least not yet) use strcpy in that case because s1.name doesn't point anywhere. You would first need to allocate memory using malloc, or perform both steps at once using strdup. Also for this reason, you can't yet use scanf until you allocate memory.
If you're not allowed to use functions from string.h, then you would need to write the characters into the array one at a time, and then write a terminating null byte at the end.
Arrays do not have the assignment operator. So these assignment statements
s1.name = { "Hussain" };
s1.name = "Hussain";
are invalid.
You could use the standard C string function strcpy to copy elements of the string literal to the array s1.name like
#include <string.h>
//...
strcpy( s1.name, "Hussain" );
If you may not use standard string functions then you need to write a loop as for example
const char *p = "Hussain";
for ( char *t = s1.name; ( *t++ = *p++ ) != '\0'; );
Or
for ( char *t = s1.name, *p = "Hussain"; ( *t++ = *p++ ) != '\0'; );
Pay attention to that the second your program has undefined behavior. The pointer s1.name is not initialized and does not point to a valid object of an array type. So the call of scanf in this code snippet invokes undefined behavior.
struct Student s1;
printf("Enter studen's name:\n");
scanf("%s",s1.name);
If you can't use <string.h>, then you have to implement your own version of strcpy():
void copystring(char *dest, const char *src)
{
const char *p = src;
while (*p) {
*dest = *p;
p++;
dest++;
}
*dest = '\0'; // Null-terminate string (as pointed by #Ted)
}
Make sure that dest has enough space to hold src.
Also, avoid using scanf() in your code. Use fgets() as an alternative.
EDIT: As pointed by Jabberwocky, fgets() leaves \n read in the string. But since using <string.h> is not allowed, you have to implement your own function to replace it with a null-terminator:
int findchar(const char *str, char c)
{
int pos;
for (pos = 0; str[pos]; ++pos)
if (str[pos] == c)
return pos;
return -1;
}
You can use it like:
char str[100];
if (!fgets(str, sizeof str, stdin)) {
// fgets() failed. Do something.
} else {
int nwln = findchar(str, '\n');
if (nwln == -1) {
// You probably entered more than 100 characters
// because \n couldn't be found.
} else {
str[nwln] = '\0';
}
}

Why am I able to modify char * in this example?

I have problems understanding how char* works.
In the example below, the struses is called by main().
I created a buf to store the const variable because I want to make a modifiable copy of s1, then I just call the sortString().
This version makes sense to me as I understand that char[] can be modified:
#include "common.h"
#include <stdbool.h>
void sortString(char string[50]);
bool struses(const char *s1, const char *s2)
{
char buf[50];
strcpy(buf, s1); // <===== input = "perpetuity";
sortString(buf);
printf("%s\n", buf); // prints "eeipprttuy"
return true;
}
void sortString(char string[50])
{
char temp;
int n = strlen(string);
for (int i = 0; i < n - 1; i++)
{
for (int j = i + 1; j < n; j++)
{
if (string[i] > string[j])
{
temp = string[i];
string[i] = string[j];
string[j] = temp;
}
}
}
}
However, in this version I deliberately changed the type to char* which is supposed to be read-only. Why do I still get the same result?
#include "common.h"
#include <stdbool.h>
void sortString(char *string);
bool struses(const char *s1, const char *s2)
{
char buf[50];
strcpy(buf, s1);
sortString(buf);
printf("%s\n", buf);
return true;
}
void sortString(char *string) // <==== changed the type
{
char temp;
int n = strlen(string);
for (int i = 0; i < n - 1; i++)
{
for (int j = i + 1; j < n; j++)
{
if (string[i] > string[j])
{
temp = string[i];
string[i] = string[j];
string[j] = temp;
}
}
}
}
This is why I think char * is read only. I get a bus error after trying to to modify read[0]:
char * read = "Hello";
read[0]='B';// <=== Bus error
printf("%s\n", read);
The compiler adjusts the type of the parameter having an array type of this function declaration
void sortString(char string[50]);
to pointer to the element type
void sortString(char *string);
So for example these function declarations are equivalent and declare the same one function
void sortString(char string[100]);
void sortString(char string[50]);
void sortString(char string[]);
void sortString(char *string);
Within this function
void sortString(char *string)
there is used the character array buf that stores the copy of the passed array (or of the passed string literal through a pointer to it)
char buf[50];
strcpy(buf, s1);
sortString(buf);
So there is no problem. s1 can be a pointer to a string literal. But the content of the string literal is copied in the character array buf that is being changed
As for this code snippet
char * read = "Hello";
read[0]='B';
printf("%s\n", read); <=== still prints "Hello"
then it has undefined behavior because you may not change a string literal.
From the C Standard (6.4.5 String literals)
7 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.
Pay attention to that in C++ opposite to C string literals have types of constant character arrays. It is advisable also in C to declare pointers to string literals with the qualifier const to avoid undefined behavior as for example
const char * read = "Hello";
By the way the function sortString has redundant swappings of elements in the passed string. It is better to declare and define it the following way
// Selection sort
char * sortString( char *s )
{
for ( size_t i = 0, n = strlen( s ); i != n; i++ )
{
size_t min_i = i;
for ( size_t j = i + 1; j != n; j++ )
{
if ( s[j] < s[min_i] )
{
min_i = j;
}
}
if ( i != min_i )
{
char c = s[i];
s[i] = s[min_i];
s[min_i] = c;
}
}
return s;
}
char * does not mean read-only. char * simply means pointer to char.
You have likely been taught that string literals, such as "Hello", may not be modified. That is not quite true; a correct statement is that the C standard does not define what happens when you attempt to modify a string literal, and C implementations commonly place string literals in read-only memory.
We can define objects with the const qualifier to say we intend not to modify them and to allow the compiler to place them in read-only memory (although it is not obligated to). If we were defining the C language from scratch, we would specify that string literals are const-qualified, the pointers that come from string literals would be const char *.
However, when C was first developed, there was no const, and string literals produced pointers that were just char *. The const qualifier came later, and it is too late the change string literals to be const-qualified because of all the old code using char *.
Because of this, it is possible that a char * points to characters in a string literal that should not be modified (because the behavior is not defined). But char * in general does not mean read-only.
Your premise that the area pointed by a char* isn't modifiable is false. This is perfectly line:
char s[] = "abc"; // Same as: char s[4] = { 'a', 'b', 'c', 0 };
char *p = s; // Same as: char *p = &(s[0]);
*p = 'A';
printf("%s\n", p); // Abc
Demo
The reason you had a fault is because you tried to modify the string created by a string literal. This is undefined behaviour:
char *p = "abc";
*p = 'A'; // Undefined behaviour
printf("%s\n", p);
One would normally use a const char * for such strings.
const char *p = "abc";
*p = 'A'; // Compilation error.
printf("%s\n", p);
Demo
Regarding
char * read = "Hello";
read[0]='B';
printf("%s\n", read); // still prints "Hello"
you have tripped over a backward compatibility wart in the C specification.
String constants are read-only. char *, however, is a pointer to modifiable data.
The type of a string constant ought to be const char [N] where N is the number of chars given by the contents of the constant, plus one. However, const did not exist in the original C language (prior to C89). So there was, in 1989, a whole lot of code that used char * to point to string constants. So the C committee made the type of string constants be char [N], even though they are read-only, to keep that code working.
Writing through a char * that points to a string constant triggers undefined behavior; anything can happen. I would have expected a crash, but the write getting discarded is not terribly surprising either.
In C++ the type of string constants is in fact const char [N] and the above fragment would have failed to compile. Some C compilers have an optional mode you can turn on that changes the type of string constants to const char [N]; for instance, GCC and clang have the -Wwrite-strings command line option. Using this mode for new programs is a good idea.
Yout long examples can be reduced to your last question.
This is why I think char * is read only, get bus error after attempt
to modify read[0]
char * read = "Hello";
read[0]='B';
printf("%s\n", read); <=== Bus error
"Hello" is a string literal . Attempt to modify the string literal manifested itself by the Bus Error.
Your pointer is referencing the memory which should not be modified.
How to sort it out? You need to define pointer referencing the modifiable object
char * read = (char []){"Hello"};
read[0]='B';
printf("%s\n", read);
So as you see declaring it as modifiable is not making it modifiable.

function for reversing an array in C (K&R 2nd ed.)

Trying to do Exercise 1-19 of K&R 2nd ed., e.g. writing a function to reverse a string. I thought I managed, but the print output looks strange :-) If I use STRINGSIZE 5 the output is
Original String: hello
Reversed String: ollehhello. If I use STRINGSIZE 6 to keep in mind the '\0' string end character and modify the while-loop to while ((outputString[STRINGSIZE - (i + 2)] = inputString[i]) != '\0'), then I get Original String: hello
Reversed String: olleh?hello, I guess the ? is some random character coming from a '\0' added to the reversed string in the while-loop at position 5; but hello is again added. Could anyone explain how come hello gets added to the end of olleh and how can I get rid of it so that I only get the proper reversed string ?
Here is the code:
#include <stdio.h>
#define STRINGSIZE 5
void reverseString (char inputString[], char outputString[]);
int main(void) {
char stringToReverse[] = "hello";
char reversedString[STRINGSIZE];
reverseString(stringToReverse, reversedString);
printf("Original String: %s\nReversed String: %s\n", stringToReverse, reversedString);
}
void reverseString (char inputString[], char outputString[]) {
int i;
i = 0;
while ((outputString[STRINGSIZE - (i + 1)] = inputString[i]) != '\0')
++i;
}
First, the character array reversedString[] does not have enough space to store the null terminator of the string "hello". One option is to use a variable length array here:
char reversedString[strlen(stringToReverse) + 1];
VLAs were introduced in C99, and made optional in C11. As I remember it, K&R does not include coverage of variable length arrays, since even the 2nd edition was published before this.
Another option that would be compatible with C89 is to use the sizeof operator:
char stringToReverse[] = "hello";
char reversedString[sizeof stringToReverse];
Here, the result from the sizeof operator is known at compile time, and can be used in the declaration of a fixed size array. This size includes space for the null terminator, in contrast to the result from strlen("hello"). Note that this would not work with char *stringToReverse = "hello";, since then the sizeof operator would give the size of a pointer. This also would not work if stringToReverse had been passed into a function first, since then the array name would have decayed to a pointer to the first element of stringToReverse.
In the reverseString() function, the length of inputString needs to be determined (since STRINGSIZE is no longer being used); this can be done with strlen(), or in a loop. Then, critically, the function must be certain to add a null terminator (\0) to outputString[] before returning. Also note that a return statement has been added to the end of main() to make this truly C89 compatible:
#include <stdio.h>
void reverseString (char inputString[], char outputString[]);
int main(void) {
char stringToReverse[] = "hello";
char reversedString[sizeof stringToReverse];
reverseString(stringToReverse, reversedString);
printf("Original String: %s\nReversed String: %s\n",
stringToReverse, reversedString);
return 0;
}
void reverseString(char inputString[], char outputString[])
{
int length = 0;
int i = 0;
/* Get inputString length; or use strlen() */
while (inputString[length] != '\0') {
++length;
}
/* Copy to outputString[] in reverse */
while (i < length) {
outputString[i] = inputString[(length - i) - 1];
++i;
}
/* Add null terminator */
outputString[i] = '\0';
}
First I'll suggest that you change this line:
char reversedString[STRINGSIZE];
to
char reversedString[strlen(stringToReverse) + 1]; // + 1 to make room for the string termination
Then I would do something like:
void reverseString (char inputString[], char outputString[]) {
int i;
int len = strlen(inputString);
for(i=0; i<len; ++i)
{
outputString[len-i-1] = inputString[i];
}
outputString[len] = '\0'; // Terminate the string
}

Adding to an array in main via function argument

I'm not sure if I even worded the title correctly, but basically. I want to know if there is a way to add to the buff array from the hey function using the pointers in the arguments and why does it work if it does?
buf[100].
example:
int main(){
char buf[100];
hey("320244",buf);
printf("%s", buf);
}
void hey(char* s, char* result){
/*
some code that appends to result using pointers
do some stuff with s and get the result back in buf without using return.
*/
}
I have modified your code with some comments :-
#define LEN 100 //Use a macro instead of error prone digits in code
void hey(char* s, char* result); //Fwd declaration
int main(){
char buf[LEN] = {0}; //This will initialize the buffer on stack
hey("320244",buf);
printf("%s", buf);
hey("abc", buf); //Possible future invocation
printf("%s", buf);
}
void hey(char* s, char* result){
if(strlen(result) + strlen(s) < LEN ) //This will check buffer overflow
strcat(result, s); //This will concatenate s into result
else
//Do some error handling here
}
Let's do the right thing, and use a structure to describe a dynamically allocated, grow-as-needed string:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
struct mystring {
char *ptr; /* The actual string */
size_t len; /* The length of the string */
size_t max; /* Maximum number of chars allocated for */
};
#define MYSTRING_INIT { NULL, 0, 0 }
If we want to append something to a struct mystring, we define a function that takes a pointer to the structure the function can modify. (If it only needed a char pointer instead of a structure, it'd take a char **; a pointer to a char pointer.)
void mystring_append(struct mystring *ms, const char *s)
{
const size_t slen = (s) ? strlen(s) : 0;
/* Make sure ms points to a struct mystring; is not NULL */
if (!ms) {
fprintf(stderr, "mystring_append(): No struct mystring specified; ms == NULL!\n");
exit(EXIT_FAILURE);
}
/* Make sure we have enough memory allocated for the data */
if (ms->len + slen >= ms->max) {
const size_t max = ms->len + slen + 1;
char *ptr;
ptr = realloc(ms->ptr, max);
if (!ptr) {
fprintf(stderr, "mystring_append(): Out of memory!\n");
exit(EXIT_FAILURE);
}
ms->max = max;
ms->ptr = ptr;
}
/* Append. */
if (slen > 0) {
memmove(ms->ptr + ms->len, s, slen);
ms->len += slen;
}
/* We allocated one char extra for the
string-terminating nul byte, '\0'. */
ms->ptr[ms->len] = '\0';
/* Done! */
}
The (s) ? strlen(s) : 0; expression uses the ?: conditional operator. Essentially, if s is non-NULL, the expression evaluates to strlen(s), otherwise it evaluates to 0. You could use
size_t slen;
if (s != NULL)
slen = strlen(s);
else
slen = 0;
instead; I just like the concise const size_t slen = (s) ? strlen(s) : 0 form better. (The const tells the compiler that the slen variable is not going to be modified. While it might help the compiler generate better code, it is mostly a hint to other programmers that slen will have this particular value all through this function, so they do not need to check if it might be modified somewhere. It helps code maintenance in the long term, so it is a very good habit to get into.)
Normally, functions return success or error. For ease of use, mystring_append() does not return anything. If there is an error, it prints an error message to standard output, and stops the program.
It is a good practice to create a function that releases any dynamic memory used by such a structure. For example,
void mystring_free(struct mystring *ms)
{
if (ms) {
free(ms->ptr);
ms->ptr = NULL;
ms->len = 0;
ms->max = 0;
}
}
Often, you see initialization functions as well, like
void mystring_init(struct mystring *ms)
{
ms->ptr = NULL;
ms->len = 0;
ms->max = 0;
}
but I prefer initialization macros like MYSTRING_INIT, defined earlier.
You can use the above in a program like this:
int main(void)
{
struct mystring message = MYSTRING_INIT;
mystring_append(&message, "Hello, ");
mystring_append(&message, "world!");
printf("message = '%s'.\n", message.ptr);
mystring_free(&message);
return EXIT_SUCCESS;
}
Notes:
When we declare a variable of the structure type (and not as a pointer to the structure, i.e. no *), we use . between the variable name and the field name. In main(), we have struct mystring message;, so we use message.ptr to refer to the char pointer in the message structure.
When we declare a variable as a pointer to a structure type (as in the functions, with * before the variable name), we use -> between the variable name and the field name. For example, in mystring_append() we have struct mystring *ms, so we use ms->ptr to refer to the char pointer in the structure pointed to by the ms variable.
Dynamic memory management is not difficult. realloc(NULL, size) is equivalent to malloc(size), and free(NULL) is safe (does nothing).
In the above function, we just need to keep track of both current length, and the number of chars allocated for the dynamic buffer pointed to by field ptr, and remember that a string needs that terminating nul byte, '\0', which is not counted in its length.
The above function reallocates only just enough memory for the additional string. In practice, extra memory is often allocated, so that the number of reallocations needed is kept to a minimum. (This is because memory allocation/reallocation functions are considered expensive, or slow, compared to other operations.) That is a topic for another occasion, though.
If we want a function to be able to modify a variable (be that any type, even a structure) in the callers scope -- struct mystring message; in main() in the above example --, the function needs to take a pointer to variable of that type, and modify the value via the pointer.
The address-of operator, &, takes the address of some variable. In particular, &message in the above example evaluates to a pointer to a struct mystring.
If we write struct mystring *ref = &message;, with struct mystring message;, then message is a variable of struct mystring type, and ref is a pointer to message; ref being of struct mystring * type.
If I have understood you correctly you mean the following
#include <string.h>
//...
void hey(char* s, char* result)
{
strcpy( result, s );
}
Here is a demonstrative program
#include <stdio.h>
#include <string.h>
void hey( const char* s, char* result);
int main(void)
{
char buf[100];
hey( "320244", buf );
printf( "%s\n", buf );
return 0;
}
void hey( const char* s, char* result )
{
strcpy( result, s );
}
Its output is
320244
If the array buf already stores a string then you can append to it a new string. For example
#include <string.h>
//...
char buf[100] = "ABC";
strcat( buf, "320244" );
Take into account that the function hey should be declared before its usage and according to the C Standard the function main shall be declared like
int main( void )

C: reverse string function not affecting pointer

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int reverse(char *, int);
main()
{
char *word = "Thanks for your help";
reverse(word, strlen(word));
printf("%s", word);
getchar();
}
int reverse(char *line, int len)
{
int i, j;
char *newline = malloc(strlen(line));
for (i = len - 1, j = 0 ; i >= 0; i--, j++)
{
newline[j] = line[i];
}
newline[j] = '\0';
line = &newline;
}
Hey folks. I've got a simple C question that I can't seem to solve.
The program above is meant to take in a string and print it out backwards. Reverse is the function by which this is done.
The issue, specifically, is that when I print word in main(), the string appears unchanged. I've attempted to make the address of line the address of newline, but it doesn't have any effect.
int reverse(char *line, int len)
{
int i, j;
char *newline = malloc(strlen(line));
for (i = len - 1, j = 0 ; i >= 0; i--, j++)
{
newline[j] = line[i];
}
newline[j] = '\0';
line = &newline; // Your problem is here
}
You're merely assigning to the local line pointer. This has no effect on the calling function whatsoever.
Consider instead:
char *reverse(char *line, int len)
{
// ...
return newline;
}
Additional advice:
Turn on compiler warnings, and heed them. You've got lots of little things wrong (e.g. reverse isn't currently returning anything, but is declared as returning int).
Given that the first argument of reverse is a pointer to a C string (NUL-terminated), there's no need to take a length argument as well.
A reverse function doesn't necessarily need to be defined as returning a copy of the string, reversed. It could instead reverse a string in-place. Note that you cannot pass a string literal to a function like this, as they are read-only.
Here's how I would write this:
#include <stdio.h>
#include <string.h>
void reverse(char *str)
{
size_t i, j;
for (i = strlen(str) - 1, j = 0 ; i > j; i--, j++)
{
// Swap characters
char c = str[i];
str[i] = str[j];
str[j] = c;
}
}
int main(void)
{
// Mutable string allocated on the stack;
// we cannot just pass a string literal to reverse().
char str[] = "Here is a test string";
reverse(str);
printf("Result: \"%s\"\n", str);
return 0;
}
Note that the for loop condition is i > j, because we want each to only traverse half the array, and not swap each character twice.
Result:
$ ./a.exe
Result: "gnirts tset a si ereH"
Take a look at the code below:
void addOne(int a) {
int newA = a + 1;
a = newA;
}
int main() {
int num = 5;
addOne(num);
printf("%d\n", num);
}
Do you see why that will print 5, and not 6? It's because when you pass num to addOne, you actually make a copy of num. When addOne changes a to newA, it is changing the copy (called a), not the original variable, num. C has pass-by-value semantics.
Your code suffers from the same problem (and a couple other things). When you call reverse, a copy of word is made (not a copy of the string, but a copy of the character pointer, which points to the string). When you change line to point to your new string, newLine, you are not actually changing the passed-in pointer; you are changing the copy of the pointer.
So, how should you implement reverse? It depends: there are a couple options.
reverse could return a newly allocated string containing the original string, reversed. In this case, your function signature would be char *reverse, instead of int reverse.
reverse could modify the original string in place. That is, you never allocate a new string, and simply move the characters of the original string around. This works, in general, but not in your case because char pointers initialized with string literals do not necessarily point to writable memory.
reverse could actually change the passed-in pointer to point at a new string (what you are trying to do in your current code). To do this, you'd have to write a function void reverse(char **pointerToString). Then you could assign *pointerToString = newLine;. But this is not great practice. The original passed-in argument is now inaccessible, and if it was malloc'd, it can't be freed.

Resources