C. for loop with chars - c

Can you explain these outputs?
1)
char s[]="TvNnFs",*p;
for(p=&s[5];p>=s;p--)
--*p;
puts(s);
OUTPUT: SuMmEr
2)
char s[]="TvNnFs",*p;
for(p=&s[5]; p>=s; p--)
((--*p)<'a') ? (*p+=('a'-'A')) : (*p);
puts(s);
OUTPUT:summer

This
char s[]="TvNnFs",*p;
where s is an array of characters and p is character pointer, is looks like below
s[0] s[1] s[2] s[3] s[4] s[5] s[6]
------------------------------------------
| T | v | N | n | F | s | \0 |
------------------------------------------
s 0x100 0x101 0x102 0x103 0x104 0x105 0x106.. (assume 0x100 is base address of s)
Next, the for loop
for(p=&s[5];p>=s;p--)
--*p;
Here p=&s[5] the pointer p points to address of s[5] i.e 0x105. Next is p>=s i.e 0x105 >= 0x100 which is true, then --*p executes i.e first *p that means value at 0x105 memory location which is s and decrements on that will makes s[5] as r.
Now char array s looks like
s[0] s[1] s[2] s[3] s[4] s[5] s[6]
---------------------------------------------
| T | v | N | n | F | r(new)| \0 |
---------------------------------------------
s 0x100 0x101 0x102 0x103 0x104 0x105 0x106..
Note : you might interested to know that by doing --*p how does s got affected ? Its because p is pointing or holding the address of s i.e whatever changes are done on *p will affect indirectly to s.
After that p-- happens i.e p now points to one location previous than before i.e 0x104. Same operation will happens until p reach to s i.e 0x100 >= 0x100. Finally char array s looks like
s[0] s[1] s[2] s[3] s[4] s[5] s[6]
-------------------------------------------
| S | u | M | m | E | r | \0 |
-------------------------------------------
s 0x100 0x101 0x102 0x103 0x104 0x105 0x106..
Hence it prints SuMmEr.
Case 2 :
char s[]="TvNnFs",*p;
for(p=&s[5]; p>=s; p--)
((--*p)<'a')?(*p+=('a'-'A')):(*p);
puts(s);
Here
s[0] s[1] s[2] s[3] s[4] s[5] s[6]
------------------------------------------
| T | v | N | n | F | s | \0 |
------------------------------------------
s 0x100 0x101 0x102 0x103 0x104 0x105 0x106..
|
p points here
For 0x105 >= 0x100 : this
((--*p)<'a')?(*p+=('a'-'A')):(*p);
is ternary operator i.e first ((--*p)<'a') executes, if it results in true then (*p+=('a'-'A')) will be the output else (*p). So Here it looks like ((--*p)<'a') i.e 'r' < 'a' which is false so just (*p) but s[5] got changed after this due to --*p.
s[0] s[1] s[2] s[3] s[4] s[5] s[6]
------------------------------------------
| T | v | N | n | F | r | \0 |
------------------------------------------
s 0x100 0x101 0x102 0x103 0x104 0x105 0x106..
|
p points here due to p--
Next, For 0x104 >= 0x100 : this
((--*p)<'a')?(*p+=('a'-'A')):(*p);
'E' < 'a' i.e 70 < 97 which is true so this (*p+=('a'-'A')) gets execute i.e
*p = *p + ('a' - 'A')
= 'E' + (97 - 65)
= 'E' + 32
*p = 'e' /* now s[4] overwritten by e(previously F) */
Now array looks like
s[0] s[1] s[2] s[3] s[4] s[5] s[6]
------------------------------------------
| T | v | N | n | e | r | \0 |
------------------------------------------
s 0x100 0x101 0x102 0x103 0x104 0x105 0x106..
|
p points here due to p--
Same operation hoes on until 0x100 >= 0x100.

Related

*a++ = *b++ (what does it mean, how it works)

What would be the values after performing this operation?
#include <stdio.h>
int main() {
int *a = 0;
int *b = 3;
*a++ = *b++;
printf("%d", a);
printf("%d", b);
return 0;
}
The code above gives me a segmentation fault.
*a++ = *b++ (what does it mean, how it works)
*a++ = *b++;
means
*(a++) = *(b++);
x++ increments x and returns the original value. So the following is equivalent:
*a = *b; // Copy the `int` to which `b` points into the `int` to which `a` points.
a = a + 1; // Make `a` point to the following `int`.
b = b + 1; // Make `b` point to the following `int`.
Before: After:
a a
+----------+ +----------+ +----------+ +----------+
| ---------->| x | | ------+ | p |
+----------+ +----------+ +----------+ | +----------+
| y | +--->| y |
+----------+ +----------+
| | | |
b b
+----------+ +----------+ +----------+ +----------+
| ---------->| p | | ------+ | p |
+----------+ +----------+ +----------+ | +----------+
| q | +--->| q |
+----------+ +----------+
| | | |
The code above gives me a segmentation fault.
You assigned garbage to a and b. 0 as a pointer is the NULL pointer, and 3 isn't a valid pointer.
Given
#include <stdio.h>
int main() {
int *a = 0;
int *b = 3;
*a++ = *b++;
printf("%d", a);
printf("%d", b);
return 0;
}
the printed values can not be predicted as the code invokes undefined behavior in multiple ways.
First, both *a and *b invoke undefined behavior by dereferencing invalid pointers - a is initialized to a null pointer value, and b is initialized to point to address 3, which is almost certainly invalid also.
Second,printf("%d", a); invokes undefined behavior by trying to print an int * variable with the %d format specifier for int. The proper code would be
printf("%p", ( void * ) a);
It's not clear what the currently-posted code is supposed to do.

Program using dynamic memory allocation

I have the below program in C. How did p[0][0] become 1? Can somebody help in understanding?
#include <stdio.h>
#include<stdlib.h>
main()
{
int i,j;
int **p=(int **)malloc(2 * sizeof(int *));
p[0]=(int*) malloc(2*sizeof(int));
p[1]=p[0];
for(i=0;i<2;i++)
for(j=0;j<2;j++)
{
p[i][j]=i+j;
printf("%d,%d,%d",i,j,p[i][j]);
printf("\n");
}
printf("%d,%d,%d",i,j,p[0][0]);
}
the output is as below
0,0,0
0,1,1
1,0,1
1,1,2
2,2,1
The same pointer is assigned to p[0] and p[1]. This means p[0] and p[1] points at the same array. Therefore updates done via p[1] is also visible via p[0].
In the second iteration of outer for loop, 1 is assigned to p[1][0]. This makes p[0][0] to be 1.
After the following lines of code:
int **p=(int **)malloc(2 * sizeof(int *));
p[0]=(int*) malloc(2*sizeof(int));
p[1]=p[0];
this is what you have in memory:
int ** int * int
+---+ +---+ +---+
p: | | ------> | | p[0] -+-> | | p[0][0], p[1][0]
+---+ +---+ | +---+
| | p[1] -+ | | p[0][1], p[1][1]
+---+ +---+
p[0] and p[1] point to the same 2-element array, so anything you write to p[0][i] is reflected in p[1][i] and vice-versa.
What you probably meant to do was something like
int **p = malloc( 2 * sizeof *p ); // cast not necessary, sizeof *p == sizeof (int *)
p[0] = malloc( 2 * sizeof *p[0] );
p[1] = malloc( 2 * sizeof *p[1] );
which would give you
int ** int * int
+---+ +---+ +---+
p: | | ------> | | p[0] ----> | | p[0][0]
+---+ +---+ +---+
| | p[1] --+ | | p[0][1]
+---+ | +---+
|
| +---+
+-> | | p[1][0]
+---+
| | p[1][1]
+---+

I don't understand why some pointer addresses are like this

I'm studying pointer in C language and I have some questions.
#include <stdio.h>
int main()
{
char c = 'A';
char* pc = &c;
char** ppc = &pc;
printf("%p %p\n", pc, ppc);
printf("%p %p\n", pc + 1, ppc + 1);
printf("%p %p\n", &c, &c + 1);
printf("%p %p\n", &pc, &ppc);
printf("%p %p\n", &pc + 1, &ppc + 1);
return 0;
}
In this code, let's say that
&c = 0117FE7B
&pc = 0117FE6C
&ppc = 0117FE60
I thought some answers will be like this:
ppc + 1 = 0117FE6D
&pc + 1 = 0117FE6D
&ppc + 1 = 0117FE61
but the correct answer was like this:
ppc + 1 = 0117FE70
&pc + 1 = 0117FE70
&ppc + 1 = 0117FE64
and I don't understand why. Can someone explain this for me?
(My computer is using 64 bit windows OS.)
Pointer arithmetic is done in terms objects, not bytes. If p evaluates to the address of a 4-byte int object, then p + 1 evaluates to the address of the next 4-byte int, not the next byte:
int x; // assume 4-byte int
int *ip = &x;
short s; // assume 2-byte short
short *sp = &s;
char c;
char *cp = &c;
+---+ +---+ +---+
x : | | <-- ip s : | | <-- sp c : | | <-- cp
+---+ +---+ +---+
| | | | | | <-- cp + 1
+---+ +---+ +---+
| | | | <-- sp + 1 | |
+---+ +---+ +---+
| | | | | |
+---+ +---+ +---+
| | <-- ip + 1 | | | |
+---+ +---+ +---+
| | | | | |
+---+ +---+ +---+
| | | | | |
+---+ +---+ +---+
| | | | | |
+---+ +---+ +---+
So depending on the size of the pointed-to type, p + 1 will either give the address + 1, or the address + 4, or the address + 8, etc.
Remember, the array subscript operation a[i] is defined as *(a + i) - given a starting address a, offset i objects (not bytes!!) from that address and deference the result.

Print binary of an ascii character

I am using the following approach to print the binary of an ascii character:
unsigned char bitmask = 0b10000000;
char _my_char = 'a';
for (int i=0; i<8; i++) {
if (i==4) putchar(' '); // separate every four characters
printf("%d", (_my_char & bitmask) != 0);
bitmask = bitmask >> 1;
}
putchar('\n');
return 0;
How could I generalize this so that, for example, I could print the binary of any data type/structure? One byte per row?
There are numerous ways to do this. The following outputs a nice chart of printable characters giving the value for each character in ASCII, decimal, hex and binary, e.g.
#include <stdio.h>
#include <limits.h>
/* CHAR_BIT */
#ifndef CHAR_BIT
#define CHAR_BIT 8
#endif
int main (void) {
char c = 0; /* character */
int i = 0; /* int loop counter */
printf ("\nchar | int | hex | binary\n");
printf ("-----+-------+--------+---------\n");
for (c = 32; c <= 126; c++) { /* for each char in printable range */
/* output the character, decimal, hex and binary */
printf (" %c | %3d | 0x%02x | ", c, c, c);
for (i = sizeof (c) * CHAR_BIT - 1; i >= 0; i--) /* for each bit */
printf ("%d", ((c >> i) & 0x1) ? 1 : 0); /* output 0/1 */
putchar ('\n'); /* output \n */
}
putchar ('\n');
}
Example Use/Output
$ ./bin/bin_ascii
char | int | hex | binary
-----+-------+--------+---------
| 32 | 0x20 | 00100000
! | 33 | 0x21 | 00100001
" | 34 | 0x22 | 00100010
# | 35 | 0x23 | 00100011
$ | 36 | 0x24 | 00100100
% | 37 | 0x25 | 00100101
& | 38 | 0x26 | 00100110
' | 39 | 0x27 | 00100111
( | 40 | 0x28 | 00101000
) | 41 | 0x29 | 00101001
* | 42 | 0x2a | 00101010
+ | 43 | 0x2b | 00101011
, | 44 | 0x2c | 00101100
- | 45 | 0x2d | 00101101
. | 46 | 0x2e | 00101110
/ | 47 | 0x2f | 00101111
0 | 48 | 0x30 | 00110000
1 | 49 | 0x31 | 00110001
2 | 50 | 0x32 | 00110010
3 | 51 | 0x33 | 00110011
4 | 52 | 0x34 | 00110100
5 | 53 | 0x35 | 00110101
6 | 54 | 0x36 | 00110110
7 | 55 | 0x37 | 00110111
8 | 56 | 0x38 | 00111000
9 | 57 | 0x39 | 00111001
<snip>
p | 112 | 0x70 | 01110000
q | 113 | 0x71 | 01110001
r | 114 | 0x72 | 01110010
s | 115 | 0x73 | 01110011
t | 116 | 0x74 | 01110100
u | 117 | 0x75 | 01110101
v | 118 | 0x76 | 01110110
w | 119 | 0x77 | 01110111
x | 120 | 0x78 | 01111000
y | 121 | 0x79 | 01111001
z | 122 | 0x7a | 01111010
{ | 123 | 0x7b | 01111011
| | 124 | 0x7c | 01111100
} | 125 | 0x7d | 01111101
~ | 126 | 0x7e | 01111110
Let me know if you have any questions about the logic.
You could create a function which takes a void pointer and the size of the structure as input.
void printdata(void *data, size_t len)
{
char my_char;
for (size_t m = 0; m < len; m++)
{
my_char = *(((char*) data) + m);
for (size_t i=0; i<8; i++)
{
if (i==4) printf(" "); // separate every four characters
printf("%d", (my_char & bitmask) != 0);
bitmask = bitmask >> 1;
}
printf("\n");
}
}
Then you can call this function for each element of your struct.
e.g.
typedef struct
{
int a;
char b;
int c[20];
}my_struct_t;
my_struct_t mystruct;
..
printdata(mystruct.a,sizeof(int));
printdata(mystruct.b,sizeof(char));
printdata(mystruct.c, 20*sizeof(int));
You can also pass the entire struct to the above function, but it will also print the padding bytes which is not what is needed.
This fit types what you want
#include <stdio.h>
#include <stdlib.h>
#define bitmask 0b1
void F1(void *a,int Len){
int i,j;
unsigned char*b=(unsigned char*)a;
b+=Len-1;
for(i=0;i<Len;i++,b--){
for(j=7;j>-1;j--){
printf("%d",((*b)&bitmask<<j)>>j);
}
}
printf("\n");
}
int main(){
unsigned int Q=10;
F1(&Q,sizeof(unsigned int));
unsigned short QQ=10;
F1(&QQ,sizeof(unsigned short));
unsigned char QQQ=10;
F1(&QQQ,sizeof(unsigned char));
return 0;
}

Why I am only seeing the first character

Question :
I know I should be using a character array but character data are stored in as their corresponding numerical value; So we can say both int array and character array are same the only difference is; generally character uses 1 byte and int uses 4 bytes.
My Problem :
I have an int array; I am storing data into that array but when I tried to print that array using printf and %s its only printing first character from that array
When %s is used with printf it searches for null character i.e. \0, to know where to stop. In my code I am putting /0 explicitly to the end of string.
Code(Edited) :
/* Write a program to print all input lines that are longer than 80
characters. */
#include <stdio.h>
#define MAXCHAR 80
#define LINES 1000
int main() {
int i, c = 0;
int data[LINES];
while(c != EOF) {
for(i = 0; i < LINES - 1 && (c = getchar()) != EOF && c != '\n'; ++i)
data[i] = c;
printf("Value of i after for = %d\n",i );
if(c == '\n') {
data[i] = c;
++i;
}
data[i] = '\0';
if(i >= MAXCHAR + 2)
printf("%s\n",data);
printf("Value of i = %d\n",i );
}
}
If you have a char array containing the string "Hello\0" it will look like this:
+---+---+---+---+---+---+
| H | e | l | l | o |\0 |
+---+---+---+---+---+---+
Or if we show the integer value of those characters it looks like this:
+-----+-----+-----+-----+-----+-----+
| 72 | 101 | 108 | 108 | 111 | 0 |
+-----+-----+-----+-----+-----+-----+
So if we have an array of int containing the same values it looks like this:
+-----------+-----------+-----------+-----------+-----------+-----------+
| 72 | 101 | 108 | 108 | 111 | 0 |
+-----------+-----------+-----------+-----------+-----------+-----------+
Or in hexadecimal, and assuming 16-bit ints, it looks like this:
+------+------+------+------+------+------+
| 0048 | 0065 | 006C | 006C | 006F | 0000 |
+------+------+------+------+------+------+
Or looking at the individual bytes, and assuming little-endian byte order, it looks like this:
+----+----+----+----+----+----+----+----+----+----+----+----+
| 48 | 00 | 65 | 00 | 6C | 00 | 6C | 00 | 6F | 00 | 00 | 00 |
+----+----+----+----+----+----+----+----+----+----+----+----+
So if we have an int array containing the integers corresponding to the characters in a string, and if (despite the gross type incompatibility) we try to print them using printf and %s, it will look at the first byte which is 48 which is an H, and print it, but then right after that it will see a 0 byte, which it will interpret as the end of the string, and stop.

Resources