Converting an integer to binary strings in c - c

This is what I've tried, my logic is that my tmp shifting left 31 times will get compared to the user input integer I and a value of 1 or 0 will be inserted to index str[0] -> str[31] and the I null terminate str[32] with the \0.
However, I'm getting a segmentation fault.
P.S. I'm not allowed to change the parameters of this function and my professor set the size of str to be 33 in the main, which, I'm not allow to change either.
void int2bitstr(int I, char *str) {
int tmp = 1 << 31;
do{
*str++ = !!(tmp & I) + '0';
} while(tmp >>= 1);
*str = '\0';
}

Try making tmp an unsigned int. The behaviour of right-shifting a negative (signed) integer is implementation-defined, and in your case is likely shifting in 1s (the original MSB) thus causing the loop to exceed the length of str.

Related

How to shift a character by another character in C

How would I go about circle left shifting every character in a string by the corresponding character in a 'password' string.
char *shift_encrypt(char *plaintext, char *password) {
for (int i = 0; plaintext[i] != '\0'; i++) {
plaintext[i] = (plaintext[i] << password[i]) | (plaintext[i] >> (8 - password[i]));
}
return plaintext;
}
EDIT:
To clarify what I am asking, if I wanted to circle shift for example the character 'A' by the character 'p', I mean something along the lines of:
0100 0001 ('A') << 0x70 ('p')
shown bit-shifted left bit by bit
1. 1000 0010
2. 0000 0101
.
.
.
110. 0101 0000
111. 1010 0000
112. 0100 0001
So basically shifting by 1, 126 times?
To circular shift an 8-bit object with large values like 112 ('p'), mod the shift by 8u. % with a negative char and 8 is not mod so use unsigned math.
Access plaintext[i] as an unsigned char [] to avoid sign extension on right shifts.
Use size_t to index string to handle even very long strings.
Sample fix:
char *shift_encrypt2(char *plaintext, const char *password) {
unsigned char *uplaintext = (unsigned char *) plaintext;
for (size_t i = 0; uplaintext[i]; i++) {
unsigned shift = password[i] % 8u;
uplaintext[i] = (uplaintext[i] << shift) | (uplaintext[i] >> (8u - shift));
}
return plaintext;
}
Note: if the password string is shorter than than plaintext string, we have trouble. A possible fix would re-cycle through the password[].
Advanced: use restrict to allow the compiler to assume plaintext[] and password[] do not overlap and emit potentially faster code.
char *shift_encrypt2(char * restrict plaintext, const char * restrict password) {
Advanced: Code really should access password[] as an unsigned char array too, yet with common and ubiquitous 2's compliment, password[i] % 8u makes no difference.
char *shift_encrypt3(char * restrict plaintext, const char * restrict password) {
if (password[0]) {
unsigned char *uplaintext = (unsigned char *) plaintext;
const unsigned char *upassword = (const unsigned char *) password;
for (size_t i = 0; uplaintext[i]; i++) {
if (*upassword == 0) {
upassword = (const unsigned char *) password;
}
unsigned shift = *upassword++ % 8u;
uplaintext[i] = (uplaintext[i] << shift) | (uplaintext[i] >> (8u - shift));
}
}
return plaintext;
}
Disclaimer: as pointed out in the comments and explained here the C standard does not guarantee that letters are contiguous. However the idea behind this answer still holds.
Characters are defined as linear entries in an ASCII table. This means that each character is represented by a number. Adding 1 to a character brings you to the next one and so on.
You should also be familiar with modular arithmetic. What is "Z"
+1? It goes back to "a".
Putting together these information you can see how the first representable character in a string in an ASCII table is represented by the number 33 decimal and the last one is represented by 126.
You can then make a shift function to shift a letter by n:
shift_letter(L,n)
ret 33 + (((L-33)+n)%(126-33))
The L-33 is done to start from 0.
Then we add n.
We cycle back in case the result is grater than the number of possible letters. %(126-33)
We add offset again
PS:
As I said in the comments, your are shifting in the mathematical sense which not only makes no sense for the operation you want to do, but it also throws an error because shifting by 112 means multiplying by 2^112 which is just a bit too much.

Why does this djb2 implementations loop terminate?

A string is terminated by a s single null byte. Since a int is bigger then an char how can the int become 0 and terminate the loop consistenly?
source : http://www.cse.yorku.ca/~oz/hash.html
unsigned long
hash(unsigned char *str)
{
unsigned long hash = 5381;
int c;
while (c = *str++)
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
return hash;
}
Loading an integer from a smaller type does not preserve the bits that the smaller type didn't have; they are cleared (or set by sign-extension, for signed types).
So:
int x = 0xfeefd00d;
x = (char) 1;
leaves the value 1, as an integer, in x, not 0xfeedf001.
When a variable is used in an expression together with variables of different types (like in the assignment in the loop condition), there's an implicit conversion being made. Conversions only convert between types, but if possible keeps the value.
So when you reach the null-terminator in str, it's converted (promoted actually) to an int, keeping the value 0. And 0 is always "false", which ends the loop.

Why does memcmp() return 256 for a difference of 1? [duplicate]

This question already has answers here:
What does size of the memcmp return value mean?
(2 answers)
Closed 3 years ago.
So I have to recreate the memcmp() function using C and my function works as expected. It returns the difference of the first character that does not match in both strings.
My function:
int ft_memcmp(const void *s1, const void *s2, size_t n)
{
unsigned char *ptr1;
unsigned char *ptr2;
ptr1 = (unsigned char *)s1;
ptr2 = (unsigned char *)s2;
while (n && (*ptr1 == *ptr2))
{
ptr1++;
ptr2++;
n--;
}
if (n == 0)
return (0);
else
return (*ptr1 - *ptr2);
}
My main:
int main(void)
{
const char *s1 = "acc";
const char *s2 = "abc";
int res;
res = memcmp(s1, s2, 3);
printf("%i\n", res);
return (0);
}
So this main will return 256, but if you use my function (ft_memcmp) you get 1. Obviously the difference is 1 and not 256, but why does the original function return 256? With a difference of 2, I get 512...
Why does memcmp() return 256 for a difference of 1?
First, as answered by #where_is_tftp, the only thing memcmp() needs to return is 0, some positive number and some negative number on a compare.
The 256 instead of 1 - certainly because of optimization.
A good memcmp() takes advantage of doing its compare using types wider than char as it can.
Example: After considering alignment and the overall length, the first compare (using 32-bit unsigned) sees a difference, not in the 1's position (bit 0), but the 256's postilion (bit 8). Since returning 256 is just as valid as 1, no need to simplify. Remember that memcmp() is platform specific and its implementation can do the things that C code cannot - like safely access outside the array. Other details omitted here.
byte 3 2 1 0
don't care 'c' 'c' 'a'
- don't care 'c' 'b' 'a'
-----------------------------------
= don't care 0 1 0
& 0 0xFF 0xFF 0xFF
-----------------------------------
= 0 0 1 0 --> 256
I cannot find a statement about exact value of non-zero return value from memcmp beside it's sign (either on man pages or Open Group pages):
The sign of a non-zero return value shall be determined by the sign of
the difference between the values of the first pair of bytes (both
interpreted as type unsigned char) that differ in the objects being
compared.
RETURN VALUE
The memcmp() function shall return an integer greater than, equal to,
or less than 0, if the object pointed to by s1 is greater than, equal
to, or less than the object pointed to by s2, respectively.
Nothing says here it is the decimal difference between characters.

In C, how am I able to use the printf() function to 'store' a string?

I am attempting to represent a bit16 representation of a number (floating point representation) using unsigned integers. The fraction field here deviates from the standard of 10, and is 8 bits - implying the exponent field is 7 bits and the sign is 1 bit.
The code I have is as follows:
bit16 float_16(bit16 sign, bit16 exp, bit16 frac) {
//make the sign the number before binary point, make the fraction binary.
//concatenate the sign then exponent then fraction
//
bit16 result;
int theExponent;
theExponent = exp + 63; // bias = 2^(7-1) + 1 = 2^6 + 1 = 63
//printf("%d",sign);
int c, k;
for(c = 6; c > 0; c--)
{
k = theExponent >> c;
if( k & 1)
printf("1");
else
printf("0");
}
for(c = 7; c >= 0; c--)
{
k = frac >> c;
if( k & 1)
printf("1");
else
printf("0");
}
//return result;
}
My thinking to 'recreate' a 16 bit sequence from these fields is to concatenate them together as so, but if I want to use them in a further application I am unable to do so. Is there a way to store the final result after everything has been printed (16-bit sequence) into a variable which can then be represented as an unsigned integer? Or is there a more optimal way to do this procedure?
While printf will not work in this case (you can't 'store' it's result), you can use sprintf.
int sprintf ( char * output_str, const char * format, ... );
sprintf writes formatted data to string
Composes a string with the same text that would be printed if format was used on printf, but instead of being printed (or displayed on the console), the content is stored as a C string in the buffer pointed by output_str.
The size of the buffer should be large enough to contain the entire resulting string. See Buffer Overflow.
A terminating null character (\0) will automatically be appended at the end of your output_str.
From output_str to an integer variable
You can use the atoi function to do this. You can get your answer in an integer variable like this:
int i = atoi (output_str);

c and bit shifting in a char

I am new to C and having a hard time understanding why the code below prints out ffffffff when binary 1111111 should equal hex ff.
int i;
char num[8] = "11111111";
unsigned char result = 0;
for ( i = 0; i < 8; ++i )
result |= (num[i] == '1') << (7 - i);
}
printf("%X", bytedata);
You print bytedata which may be uninitialized.
Replace
printf("%X", bytedata);
with
printf("%X", result);
Your code then run's fine. code
Although it is legal in C, for good practice you should make
char num[8] = "11111111";
to
char num[9] = "11111111";
because in C the null character ('\0') always appended to the string literal. And also it would not compile as a C++ file with g++.
EDIT
To answer your question
If I use char the result is FFFFFFFF but if I use unsigned char the result is FF.
Answer:
Case 1:
In C size of char is 1byte(Most implementation). If it is unsigned we can
use 8bit and hold maximum 11111111 in binary and FF in hex(decimal 255). When you print it with printf("%X", result);, this value implicitly converted to unsigned int which becomes FF in hex.
Case 2: But when you use char(signed), then MSB bit use as sign bit, so you can use at most 7 bit for your number whose range -128 to 127 in decimal. When you assign it with FF(255 in decimal) then Integer Overflow occur which leads to Undefined behavior.

Resources