Problems writing the memset function - c

I am writing the memset function and my code is below, I am having a problem
void* memsetFun(void* pointer, int c, int size) {
if ( pointer != NULL && size > 0 ) {
unsigned char* pChar = pointer;
int i = 0;
for ( i = 0; i < size; ++i) {
unsigned char temp = (unsigned char) c;
*pChar++ = temp; // or pChar[i] = temp (they both don't work)
}
}
return pointer;
}
I also tried pChar[i] = the value we want and still not working. It gives me some trash numbers that do not make any sense.
And I am calling it:
memsetFun(address, num, size);
printf("value at %p is %d\n", address, *((int*) address));
Where I call the address (I just input the address)
For example, if you to print the chars ( c ) it prints like a weird char that looks like ( for the value 4 )
0 0
0 4

Your code looks fine to me and several people here have commented that it works on their system.
So the obvious thing to do is to debug it - that's a skill that will come in handy quite a bit in future :-) You should learn it now.
What does the following code output when you run it?
void* memsetFun(void* pointer, int c, int size) {
printf("A %x %d %d\n", pointer, c, size);
if ( pointer != NULL && size > 0 ) {
printf("B\n");
unsigned char* pChar = pointer;
int i = 0;
for ( i = 0; i < size; ++i) {
printf("C %d (%d)", i, *pChar);
unsigned char temp = (unsigned char) c;
*pChar++ = temp; // or pChar[i] = temp (they both don't work)
printf(" -> (%d)", i, *(pChar-1));
}
}
printf("D\n");
return pointer;
}
From the output, it should be clear what paths the code is taking and what your parameters are (which will greatly assist the debugging process).
Update:
If you're filling your memory block with anything other than zeros and using this:
printf("value at %p is %d\n", address, *((int*) address));
to print it out, you will get strange results.
You're basically asking for a number of those bytes to be interpreted as an integer. So, for example, if you filled it with 0x02 bytes and you have a 4-byte integer type, you will get the integer 0x02020202 (33686018), not 0x02 as you may expect. If you want to see what the first character value is, use:
printf("value at %p is %d\n", address, *((char*) address));
And based on your latest question update:
For example, if you to print the chars ( c ) it prints like a weird char that looks like ( for the value 4 )
0 0
0 4
If that's a single character and you're printing it as a character, there's probably nothing wrong at all. Many output streams will give you that for a control character (CTRL-D in this case, ASCII code 4). If you instead filled it with ASCII code 0x30 (48), you would see the character '0' or ASCII 0x41 (65) would give you 'A'.

As pointed out already, your function works as it should. Here is a complete example:
#include <assert.h>
#include <string.h>
void* memsetFun(void* pointer, int c, int size) {
if ( pointer != NULL && size > 0 ) {
unsigned char* pChar = pointer;
int i = 0;
for ( i = 0; i < size; ++i) {
unsigned char temp = (unsigned char) c;
*pChar++ = temp; // or pChar[i] = temp (they both don't work)
}
}
return pointer;
}
int main() {
// Your memset
char a[10];
memsetFun(a, 'A', sizeof(a));
// Uses system memset for verification
char b[10];
memset(b, 'A', sizeof(b));
assert(sizeof(a) == sizeof(b));
assert(memcmp(a, b, sizeof(b)) == 0);
return 0;
}

return p; prevents this from compiling: p is not defined.
A minor efficiency issue—in practice it would have little effect, since any good compiler would rearrange it, but coding perfectionists wouldn't allow it to remain—the assignment to temp is inside the loop, but it is the same assignment every time. That is, the assignment to temp can be moved before the loop.

You return p, which isn't defined/doesn't point to anything in particular. Maybe you meant pointer?

The code is logically correct. With the p => pointer change it works correctly.
Clarify how exactly it is "not working". Perhaps you are not understanding what it is supposed to do?

You are probably getting trash numbers because you are casting from an int (4 bytes) to an unsigned char (1 byte), so if c > 255 or < 0 you won't be memsetting the values you are expecting to be.

I ran a test if your program setting the memory of an int vector of 5 elements setting with the value 0x01.
The problem here is that you are iterating in a vector of int for example (which is 4 bytes) but iterating over it using char pointer arithmetic (1 byte). If you want to memset 0x01 for example you will write this number per value in the vector: 00000001000000010000000100000001
which gives me the same value using the original memset.

Your function, as is, works for me.
I suppose you're calling it wrong. I call it like this
char a[100];
memsetFun(a, 0, sizeof a);
int b[100];
memsetFun(b, 0, sizeof b);
How are you calling your memsetFun()?
Edit
With
int b[100];
memsetFun(b, 9, sizeof b);
as an int is made up of 4 bytes (on my system) each value will be set to 0x09090909 or 151587081.

That is exactly what it's supposed to do. Your function is working perfectly fine. The value "0x4" is not the ASCII character '4'.

Related

Printing the value of memory allocated by calloc not initialized to zeroed

I'm confused about what is happening when I try to use calloc as opposed to malloc. My understanding is that calloc allocates the memory and initializes the value at each address to zero, whereas malloc just allocates the memory. However, when I attempt to print the values at each address I expect the values to be zero for calloc and random characters for malloc - But they aren't... they're the same no matter which I do.
typedef struct {
char* text;
void* obj;
} statement_t;
void* stalloc() {
return calloc(1, MODEL_OBJ_CAPACITY);
// return malloc(MODEL_OBJ_CAPACITY); Also used this
};
statement_t NewStatement(char* text) {
statement_t statement;
statement.text = text;
statement.obj = stalloc();
return statement;
};
int main(void) {
statement_t statement = NewStatement("CREATE job Manager");
for(int n = 0; n < 10; ++n) {
printf("statement[%d]: %c\n", n, (char)&statement.obj[n]); // Note I've tried a number of ways to print this but they always end up being the same
}
...
}
Output from calloc:
statement: CREATE job Manager 0x7fb127405c60 8
statement[0]: `
statement[1]: a
statement[2]: b
statement[3]: c
statement[4]: d
statement[5]: e
statement[6]: f
statement[7]: g
statement[8]: h
statement[9]: i
Output from malloc:
statement: CREATE job Manager 0x7f8becc05c60 8
statement[0]: `
statement[1]: a
statement[2]: b
statement[3]: c
statement[4]: d
statement[5]: e
statement[6]: f
statement[7]: g
statement[8]: h
statement[9]: i
As you can see, they are the same... What am I missing?
obj has type of void*. C standard does not allow any pointer arithmetics on void pointers. There is not possible to index void *.
It is is a gcc extension and it is not portable.
Try:
printf("statement[%zu]: %d\n", n, ((char *)statement.obj)[n]);
or
int c;
for(size_t n = 0; n < 10; ++n) {
c = ((char *)statement.obj)[n];
printf("statement[%zu]: %s : %d (0x%02x)\n", n, (c >= 32 && c <= 127) ? (char []){'\'', c, '\'', 0} : "not printable", c, c );
}
You're not printing correctly:
printf("statement[%d]: %c\n", n, (char)&statement.obj[n]);
You're attempting to print the address of each byte in the array, rather than the byte itself. Also, by using %c you're printing the character associated with each byte value instead of the actual value.
First cast the void * to char *, then index the array. Also, use %d to print the value of each byte:
printf("statement[%d]: %d\n", n, ((char *)statement.obj)[n]);

Bit manipulation with pointers

I was trying to understand pointers better, especially with string literals. I wanted to print a letter's bits in a string literal.
My main simply contains:
char *a = "A";
showBits(a);
and the function looks like that:
void showBits(char *character) {
int size = sizeof(char);
const unsigned int maxPow = 1<<(size*8-1); // 128
int j;
int temp = -1;
for(j=0;j<8;j++) {
temp = (*character)&maxPow;
printf("2%u", !!((*character)&maxPow));
*character = *character << 1;
}
}
Obviously the code does not work. I could make the code work with a[] = "A" but that was not my intention, I wanted to work with pointers to understand them better. I wonder, if there is a way to make this work?
I could imagine, that you can extract the bits, when you simply right shift maxPow and do a logial comparison with &, but is there a way to do it/work with the pointer?
Also I was thinking of passing the address to the function by showBits(&a), but can you then go through the addresses bit by bit?
The assignment to character tries to modify a string literal which is not possible. When you change the code to char a[] = "A", a stack-allocated array is created which is initalized with 'A''\0' and can be modified.
As a rule, you should always use a char const* when using string literals. This would have prevented the issue completely. I think the compiler should have generated a warning.
I think you could just pass the char by value and then everything will work.
void showBits(char character) {
const unsigned char maxPow = 128;
int j;
for(j=0;j<8;j++) {
printf("%u", 0 != (character & maxPow) );
character <<= 1;
}
}
int main()
{
char const* a = "\127";
showBits(*a);
}
I also simplified the function a bit because sizeof(char)is always 1 and removed some redundant code.
This is probably the most frequently asked question here (at least under C/C++).
Using "A", you have an array of characters "A\0" allocated in a read-only memory segment within your program (typically in the RO data-section).
Every time a function declaring char* a = "A" is called, a local variable is allocated on the stack and initialized to point to the address of "A\0" in memory.
Since this variable points to a read-only memory segment, any attempt to change the pointed data is likely to yield a memory access violation during runtime.
Every time a function declaring char a[] = "A" is called, a local array is allocated on the stack and initialized with the contents of "A\0" in memory.
Since this array resides in a writable memory segment, the program can safely change its contents during runtime (as long as it doesn't exceed its boundaries).
Instead of trying to do *character = *character << 1 and bitops with maxPow, just print (*character)&(1<<j).
int size_in_bits = sizeof(char)*8;
for(j=0;j<8;j++) {
printf("2%u", !!((*character)&(1<<(size_in_bits - 1 - j));
}
Try something like this:
void showBits(char *character) {
char result[10];
int mask = 0x80;
for (int j = 7; j >= 0; j -= 1) {
result[7-j] = (mask & *character) ? '1' : '0';
mask >>= 1;
}
result[8] = '\0';
printf("%s\n", result);
}
I would divide the functionality into two functions:
void showBitsOne(unsigned char c, int bits_left)
{
int bit = 0;
if ( bits_left <= 0 )
{
return;
}
// Print the bit.
bit = ((c & (1 << (bits_left-1))) == (1 << (bits_left-1)));
printf("%d", bit);
// Recurse.
showBitsOne(c, bits_left - 1);
}
void showBits(const char *character) {
while ( *character != '\0' )
{
showBitsOne(*character, CHAR_BIT);
printf(" "); // Just add a space between characters.
++character;
}
printf("\n");
}
With the following main function
int main()
{
showBits("abcd");
return 0;
}
I get the output:
01100001 01100010 01100011 01100100

shifting array element one by one

I got a homework question. I'm so close to complete program. I'm having trouble about one thing. This is the question:
Write a C program that generates and displays a character array of size 10 consisting of
random English lower-case letters. The program then asks the user how many times the array
will be right-shifted and displays the right shifted array at each right-shifting step. A sample
program execution output is given below. ( Hint: Use the ASCII codes of the English lower-case
letters which are 97, 98, ... 122 for a, b, ..., z, respectively, to generate the character array).
This is my code:
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
void print_string (char *string){
int i;
for (i=0 ; i < 10 ; i ++){
printf("%c ", string[i]);
if (i == 9)
printf("\n");
}
}
void random_string(char *string, unsigned length)
{
/* Seed number for rand() */
srand((unsigned int) time(0) + getpid());
/* ASCII characters 97 to 122 */
int i;
for (i = 0; i < length; ++i)
{
string[i] = (rand() % 26)+ 97;
}
string[i] = '\0';
}
void reverse_string(char* str, int left, int right) {
char* p1 = str + left;
char* p2 = str + right;
while (p1 < p2) {
char temp = *p1;
*p1 = *p2;
*p2 = temp;
p1++;
p2--;
}
}
void rotate(char* str, int k, int n) {
reverse_string(str, 0, n-1);
reverse_string(str, 0, k-1);
reverse_string(str, k, n-1);
}
int main(void)
{
char s[11];
int i,shiftNum;
random_string(s, 11);
printf("Randomly constructed array is :\n");
print_string(s);
printf("Enter how many times array will be shifted: ");
scanf("%d",&shiftNum);
rotate(s,shiftNum,11);
print_string(s);
}
What's wrong with this code? When I execute it with 1, I couldn't get the first reverse correctly and I want to display all shifting steps.
For a start, it is atrocious that your lecturer/professor is telling you to use 97..122. C does not require that ASCII be the character set on every system, so this code is entirely non-portable, yet if you look at the history as far as Unix is concerned C is supposed to be a portable programming language. If you want to write this in a portable way, you need to store the characters in an array and select from that array:
char lowercase[] = "abcdefghijklmnopqrstuvwxyz";
string[i] = lowercase[rand() % (sizeof lowercase - 1)];
Now that we've covered that pedantic detail, Cool Guy indicated in a comment that this line of code is erroneous: string[i] = '\0';. He's correct about that.
This should also performed within main, not within random_string: srand((unsigned int) time(0) + getpid());. The reason is that calling random_string multiple times in the same second would result in the same "random string", which is very uncool.
scanf("%d",&shiftNum); can't guarantee success (that the user will input numeric data), and so can't guarantee that shiftNum will contain a sane value. You need to check the return value. For example:
if (scanf("%d", &shiftNum) != 1) {
puts("Invalid shift count!\n");
exit(0);
}
You should probably also consider using an unsigned type for shiftNum (and this will cause the corresponding format spec %d to change to something else, such as %u for unsigned int).
One more important task before I finish this task: You need to modify rotate to handle an input of 0 correctly, since some users might want to rotate/shift 0 times (as an alternative to not rotating/shifting at all). I'm confident that this should be an easy task for you.

Understanding unsigned 0 in C

I am trying to understand number representation in C.
I am working on a code segment which looks like the one below.
#include <stdio.h>
#include <string.h>
typedef unsigned char *byte_pointer;
void show_bytes(byte_pointer start, int len)
{
int i;
for (i = 0; i < len; i++)
printf(" %.2x", start[i]);
printf("\n");
}
void show_int(int x) {
show_bytes((byte_pointer) &x, sizeof(int));
}
void show_unsigned(short x) {
show_bytes((byte_pointer) &x, sizeof(unsigned));
}
int main(int argc,char*argv[])
{
int length=0;
unsigned g=(unsigned)length;// i aslo tried with unsigned g=0 and the bytes are the same
show_unsigned(g);
show_int(length);
printf("%d",g);//this prints 0
return 0;
}
Here, show_unsigned() and show_int() prints the byte representations of the variables specified as arguments.For int length the byte representation is all zeroes as expected, but for unsigned g, the byte representation is 00 00 04 08.But when I print g with a %d, I get 0(so i suppose the numeric value is interpreted as 0 )
Please could somebody explain how this is happening.
In:
void show_unsigned(short x) {
show_bytes((byte_pointer) &x, sizeof(unsigned));
}
You declared the argument short x which is smaller than int x so you ignored some of the 00 and your print function is displaying adjacent garbage.
You're reading sizeof(unsigned) bytes in a short. short isn't guaranteed to be the same size as unsigned, hence, when reading the bytes next to your short, garbage data is read.
To fix this, either pass your argument as an unsigned, or when using sizeof, use sizeof(short).
what you are doing doesn't make any sense, particularly with the type conversions that you have occurring. Someone else already pointed out my point about the conversion to short
Rather than writing an absurd number of functions try doing this
void show_bytes( void *start, unsigned int len ) {
unsigned char* ptr = (unsigned char *) start;
unsigned int i = 0;
for ( i = 0; i < len; ++i, ++ptr ) {
printf( " %.2x", ptr[0] );
}
}
Instead of calling as you had been just call it like:
show_bytes( (void *)&x, sizeof(x));
And if thats too much typing make a macro out of that. now it works for any type you come up with.

getting EXITED error:pointer to an array in c

int main()
{
unsigned char a[3];
unsigned char (*p)[3]=NULL;
unsigned char *q=NULL;
int i = 0;
a[0]=0;
a[1]=1;
a[2]=2;
p=&a;
for(i=0;i<3;i++){
if((*p)[3] == a[3]){
printf("*p[%d]:%d a[%d]:%d",i,(*p)[3],i,a[3]);
}
}
}
o/p:
*p[0]:0 a[0]:0*p[1]:0 a[1]:0*p[2]:0 a[2]:0
Exited: ExitFailure 14
I want to copy an array of size 3 to a pointer and to do a comparision. I have written a sample program. But i'm getting an error value.
I ran this using an online c compiler . (codepad.org)
Please help me in identifying my mistakes.
Your variable p is an array, not a pointer. You can't re-assign an array to point somewhere else, so the line
p = &a;
is not valid.
Also, C indexes from 0 as you seem to know, so comparisons using index [3] for arrays of size 3 are not valid.
Further, in your comparison loop you're not actually using i to index, but instead always comparing using the invalid constant index [3].
It's not very clear from your code (q is not used, for instance), but it sounds as if you want to do something like:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
unsigned char a[3];
unsigned char *p;
p = malloc(sizeof a);
if(p != NULL) /* If allocation succeeded, p is valid. */
{
int i;
memcpy(p, a, sizeof a);
for(i = 0; i < sizeof a; ++i)
{
if(p[i] == a[i])
printf("p[%d]:%d a[%d]:%d\n", i, p[i], i, a[i]);
}
free(p);
}
Of course, this will always print all the numbers, since memcpy() will never fail to copy the memory. :)
Here You have declared the return type of main function as int, but you are not returning anything from it.
So return any integer value (like 1) or make the main function's return type void.

Resources