Can I cast void * to ptrdiff_t in C89? - casting

Will the C89 standard allow me to cast void * to ptrdiff_t so I can print the memory location as hexadecimal?
For example:
static const char *dig = "0123456789abcdef";
char buf[16], *ptr = buf; /* Need 16 bytes when sizeof(void *) == 8 */
void *val;
ptrdiff_t tmp = (const unsigned char *) val - (const unsigned char *) 0;
do {
*buf++ = dig[tmp & 0xf];
tmp >>= 4;
} while (tmp);
do {
putc(*--ptr);
} while (ptr > buf);
Context: I am writing a printf() function in kernel space.

Related

Equivalent of wstring in C

How can I read and access Unicode characters with standard C. Previously I was using C++ and std::wstring for whole word and 'const wchar_t' for a single characters, which works perfectly( below is example code).
But now I am not allowed to use C++. How can I replace the 'wstring' in C? How can I convert my code to standard C?
...
...
const wchar_t small_char[10]={ L'锕',L'吖',L'啊',L'阿',L'呵',L'嗄',L'埃',L'哀',L'哎'};
std::wstring strIn=L"锕吖哎";
std::wstring s_temp=L"";
int length= strIn.length();
for(int i=0;i<length;i++){
if(strIn[i]==small_char[2]){
s_temp=s_temp+L"ba";
}
else if(strIn[i]==small_char[5]){
s_temp=s_temp+L"pe";
}
else{
s_temp=s_temp+strIn[i];
}
}
...
...
How can I replace the 'wstring' in C? How can I convert my code to standard C?
std::wstring is just a wrapper for wchar_t*. You can use wchar_t directly, you just have to manage the string memory and concatenations manually.
Try this:
...
const wchar_t small_char[10] = { L'锕', L'吖', L'啊', L'阿', L'呵', L'嗄', L'埃', L'哀', L'哎'};
wchar_t *strIn = L"锕吖哎";
int length = wcslen(strIn);
wchar_t *s_temp = (wchar_t*) calloc((length*2)+1, sizeof(wchar_t));
int s_temp_len = 0;
for(int i = 0; i < length; i++)
{
if (strIn[i] == small_char[2])
{
memcpy(&s_temp[s_temp_len], L"ba", 2*sizeof(wchar_t));
s_temp_len += 2;
s_temp[s_temp_len] = L'\0';
}
else if (strIn[i] == small_char[5])
{
memcpy(&s_temp[s_temp_len], L"pe", 2*sizeof(wchar_t));
s_temp_len += 2;
s_temp[s_temp_len] = L'\0';
}
else
{
s_temp[s_temp_len] = strIn[i];
s_temp_len += 1;
s_temp[s_temp_len] = L'\0';
}
}
// use s_temp up to s_temp_len characters as needed...
free(s_temp);
...
If you want something more like std::wstring, you should pre-allocate a small buffer and resize it whenever you are going to exceed its capacity during concatenations. A struct is useful for keeping track of that:
struct my_wstring
{
wchar_t *data;
int length;
int capacity;
};
void wstring_init(struct my_wstring *str)
{
str->data = NULL;
str->length = 0;
str->capacity = 0;
};
void wstring_clear(struct my_wstring *str)
{
free(str->data);
str->data = NULL;
str->length = 0;
str->capacity = 0;
};
// allocate in multiples of 32
const int delta = 32;
void wstring_append_str_len(struct my_wstring *str, const wchar_t *value, int valueLen)
{
if ((!str) || (!value) || (valueLen < 1)) return;
int newLen = str->length + valueLen;
if ((newLen + 1) > str->capacity)
{
// round to next highest multiple of 32
int newCap = ((newLen + 1) + (delta - 1)) & ~delta;
wchar_t *newData = (wchar_t*) realloc(str->data, newCap * sizeof(wchar_t));
if (!newData)
{
// memory allocation error, do something!
return;
}
str->data = newData;
str->capacity = newCap;
}
memcpy(&(str->data[str->length]), value, valueLen * sizeof(wchar_t));
str->length = newLen;
str->data[newLen] = L'\0';
}
void wstring_append_str(struct wstring *str, const wchar_t *value)
{
wstring_append_str_len(str, value, wcslen(value));
}
void wstring_append_chr(struct wstring *str, const wchar_t value)
{
wstring_append_str_len(str, &value, 1);
}
...
const wchar_t small_char[10] = { L'锕', L'吖', L'啊', L'阿', L'呵', L'嗄', L'埃', L'哀', L'哎'};
wchar_t *strIn = L"锕吖哎";
struct my_wstring s_temp;
wstring_init(&s_temp);
int length = wcslen(strIn);
for(int i = 0; i < length; i++)
{
if (strIn[i] == small_char[2])
{
wstring_append_str(&s_temp, L"ba");
}
else if (strIn[i] == small_char[5])
{
wstring_append_str(&s_temp, L"pe");
}
else
{
wstring_append_chr(&s_temp, strIn[i]);
}
}
// use s_temp.data up to s_temp.length characters as needed...
wstring_clear(&s_temp);
...
The equivalent C routines are
== wcscmp or wcsncmp
+= wcscat or wcscat_s
= wcscpy or wcsncpy or wcscpy_s
.size() or length() wcslen
In your case since you are comparing one character at a time, you do not need wcscmp. Make sure all your strings are null terminated otherwise the non _s versions won't work.

Strcpy in c++ doesn't work

Can anyone tell why strcpy in this code returns an empty string?
#include <iostream>
char* strcpy(char* dest, const char* from) {
for ( ; *from; dest++, from++) {
*dest = *from;
}
return dest;
}
int main() {
char a[] = "aba";
char b[] = "hello";
std::cout << strcpy(a, b);
return 0;
}
The compiler I'm using is GNU G++11 4.9.2
upd: this doesn't work either
#include
char* strcpy(char* dest, const char* from) {
for ( ; *from; dest++, from++) {
*dest = *from;
}
*dest = '\0';
return dest;
}
int main() {
char a[] = "abaaa";
char b[] = "hello";
std::cout << strcpy(a, b);
return 0;
}
Try using temp pointer:
char* strcpy(char* dest, const char* from) {
char *tmp = dest;
for ( ; *from; tmp++, from++) {
*tmp = *from;
}
*tmp = '\0';
return dest;
}
Also consider allocate memory for the dest with appropriate number of characters.
The function and the program itself are invalid.:)
For example array a can not accomodate all characters from array b because its size is less than the size of b. (The size of a is equal to 4 while the size of b is equal to 6)
char a[] = "aba";
char b[] = "hello";
So the call strcpy(a, b) in this statement
std::cout << strcpy(a, b);
results in undefined behaviour.
As for the function then it does not copies the terminating zero from the sourse string to the destination string. And it does not return pointer to the first character of the destination string because inside the function pointer dest is changed (it was increased)
The correct function can look like
char* strcpy( char* dest, const char* from )
{
char *p = dest;
while ( *p++ = *from++ );
return dest;
}
Instead of incrementing dest and from in the loop, try this:
char *StrCpy (char *dest, const char *from){
int i=0;
for (i=0;i<strlen(from);i++){
*(dest+i) = *(from+i);
}
*(dest+(strlen(from)))='\0';
return dest;
}

Modifying bits in a byte with a class

I want to directly modify a bit in a byte.
In GCC, you can do it as follow:
struct virtualByte {
unsigned char b0 : 1;
unsigned char b1 : 1;
unsigned char b2 : 1;
unsigned char b3 : 1;
unsigned char b4 : 1;
unsigned char b5 : 1;
unsigned char b6 : 1;
unsigned char b7 : 1;
} __attribute__((__packed__));
#define sbit(_byte, _pos) (((volatile struct virtualByte *)&_byte)->b ## _pos)
Usage:
unsigned char myByte = 0x00;
#define firstBit sbit(myByte, 0)
firstBit = 1; // Implicit myByte |= 0x01;
To make things neater I want to have class that does this for me. I came up with the following concept:
unsigned char myByteRef = 0x00;
Byte myByte(&myByteRef);
myByte[0] = 1; // Implicit myByteRef |= 0x01;
fprintf(stderr, "%2.2X\n", myByteRef);
But this does not work because in c++ you cannot return a reference to a single bit. Overloading the constructor does not work either.
Is there a possibility to implement such behaviour? The assignment operator should directly modify its underlying byte (not a set of bytes).
You want to use std::bitset:
std::bitset<12> someBits; // 12 bits
someBits[0] = true; // set 1st bit
std::cout << someBits.count() << '\n'; // prints 1
std::bitset<12>::reference bit5 = someBits[5];
bit5 = true;
std::cout << someBits.count() << '\n'; // prints 2
You can use the index operator to return a reference to a bit in the way you want. Note that this reference is not a bool& but rather a std::bitset::reference:
Finally came to a solution, many thanks to #doc!
My solution:
class Bit {
private:
volatile uint8_t *byte;
uint8_t bitPos;
public:
Bit(void)
{
}
void init(volatile uint8_t *const byte, uint8_t const bitPos)
{
this->byte = byte;
this->bitPos = (bitPos > 7u ? 7u : bitPos);
}
void setValue(bool const bitValue)
{
if (!this->byte) return;
if (bitValue) {
*this->byte |= (1u << this->bitPos);
} else {
*this->byte &= ~(1u << this->bitPos);
}
}
};
class BitReference {
private:
Bit &ref;
public:
BitReference(Bit &ref) : ref(ref)
{
}
void operator=(bool const bitValue)
{
this->ref.setValue(bitValue);
}
};
class Byte {
private:
Bit bits[8];
public:
Byte(volatile uint8_t *const byte)
{
for (unsigned i = 0; i < 8; ++i) {
this->bits[i].init(byte, i);
}
}
/* This did the trick :)! */
BitReference operator[](size_t index)
{
if (index > 7) index = 7;
return BitReference(this->bits[index]);
}
};
Usage:
uint8_t myPort = 0x00;
int main(int const argc, const char **const argv)
{
Byte abc(&myPort);
abc[0] = 1;
abc[1] = 1;
abc[2] = 1;
abc[3] = 1;
fprintf(stderr, "%2.2X\n", myPort);
return 0;
}

Encode/Decode URl In C++

How can i encode a URL in client side and Decode the same in Server side.Is there any Built in apis are available for this purpose.Please anyone suggest a solution.Also i want to know how can i do percentage encoding in C++?
I've found this implementation from dlib quite useful. You don't even need to grab the whole library, just these 4 functions (unhex, hex, encode, decode). And it has a boost license.
You can check out this article and this
Encode:
std::string UriEncode(const std::string & sSrc)
{
const char DEC2HEX[16 + 1] = "0123456789ABCDEF";
const unsigned char * pSrc = (const unsigned char *)sSrc.c_str();
const int SRC_LEN = sSrc.length();
unsigned char * const pStart = new unsigned char[SRC_LEN * 3];
unsigned char * pEnd = pStart;
const unsigned char * const SRC_END = pSrc + SRC_LEN;
for (; pSrc < SRC_END; ++pSrc)
{
if (SAFE[*pSrc])
*pEnd++ = *pSrc;
else
{
// escape this char
*pEnd++ = '%';
*pEnd++ = DEC2HEX[*pSrc >> 4];
*pEnd++ = DEC2HEX[*pSrc & 0x0F];
}
}
std::string sResult((char *)pStart, (char *)pEnd);
delete [] pStart;
return sResult;
}
Decode:
std::string UriDecode(const std::string & sSrc)
{
// Note from RFC1630: "Sequences which start with a percent
// sign but are not followed by two hexadecimal characters
// (0-9, A-F) are reserved for future extension"
const unsigned char * pSrc = (const unsigned char *)sSrc.c_str();
const int SRC_LEN = sSrc.length();
const unsigned char * const SRC_END = pSrc + SRC_LEN;
// last decodable '%'
const unsigned char * const SRC_LAST_DEC = SRC_END - 2;
char * const pStart = new char[SRC_LEN];
char * pEnd = pStart;
while (pSrc < SRC_LAST_DEC)
{
if (*pSrc == '%')
{
char dec1, dec2;
if (-1 != (dec1 = HEX2DEC[*(pSrc + 1)])
&& -1 != (dec2 = HEX2DEC[*(pSrc + 2)]))
{
*pEnd++ = (dec1 << 4) + dec2;
pSrc += 3;
continue;
}
}
*pEnd++ = *pSrc++;
}
// the last 2- chars
while (pSrc < SRC_END)
*pEnd++ = *pSrc++;
std::string sResult(pStart, pEnd);
delete [] pStart;
return sResult;
}
For Encoding:
You can use "g_uri_escape_string()" function provided glib.h.
https://developer.gnome.org/glib/stable/glib-URI-Functions.html
#include <stdio.h>
#include <stdlib.h>
#include <glib.h>
int main() {
char *uri = "http://www.example.com?hello world";
char *encoded_uri = NULL;
//as per wiki (https://en.wikipedia.org/wiki/Percent-encoding)
char *escape_char_str = "!*'();:#&=+$,/?#[]";
encoded_uri = g_uri_escape_string(uri, escape_char_str, TRUE);
printf("[%s]\n", encoded_uri);
free(encoded_uri);
return 0;
}
compile it with:
gcc encoding_URI.c `pkg-config --cflags --libs glib-2.0`

Solving C++ 'target of assignment not really an lvalue' errors

Given this code:
void FrMemCopy(void *to, const void *from, size_t sz)
{
size_t sz8 = sz >> 3;
size_t sz1 = sz - (sz8 << 3);
while (sz8-- != 0) {
*((double *)to)++ = *((double *)from)++;
}
while (sz1-- != 0) {
*((char *)to)++ = *((char *)from)++;
}
}
I am receiving target of assignment not really an lvalue warnings on the 2 lines inside the while loops.
Can anyone break down those lines?
a cast then an increment?
What is a simplier way to write that?
What does the error mean?
It does not like the *((char*)to)++ statement.
Try this:
void FrMemCopy(void *to, const void *from, size_t sz)
{
size_t sz8 = sz >> 3;
size_t sz1 = sz - (sz8 << 3);
double * tod = (double *) to;
double * fromd = (double *) from;
while (sz8-- != 0) {
*(tod++) = *(fromd++);
}
char * toc = (char *) tod;
char * fromc = (char *) fromd;
while (sz1-- != 0) {
*(toc++) = *(fromc++);
}
}
You can't apply ++ to the result of a cast, only to an lvalue (a variable). So you need to create new variable with the appropriate types for the increments:
void FrMemCopy(void *to, const void *from, size_t sz)
{
size_t sz8 = sz >> 3;
size_t sz1 = sz - (sz8 << 3);
double *to1 = (double *)to;
double *from1 = (double *)from
while (sz8-- != 0) {
*to1++ = *from1++;
}
char *to2 = (char *)to1;
char *from2 = (char *)from1;
while (sz1-- != 0) {
*to2++ = *from2++;
}
}
I tried to rewrite it in a way that no warning appears:
void FrMemCopy(void *to, const void *from, size_t sz)
{
size_t sz8 = sz >> 3;
size_t sz1 = sz - (sz8 << 3);
double *xto = (double *)to;
double *xfrom = (double *)from;
while (sz8-- != 0) {
*xto++ = *xfrom++;
}
char *cto = (char *)to;
char *cfrom = (char *)from;
while (sz1-- != 0) {
*cto++ = *cfrom++;
}
}
The result of explicit type conversion is rvalue in this case - according to 5.4.1 of C++11 Standard. You cannot apply increment operator to rvalue, it shall be lvalue. See C++ value category for details.
Use temporary variables to obtain required effect:
double* to_dbl = static_cast<double*>(to);
double* from_dbl = static_cast<double*>(from);
while(sz8-- != 0)
{
*(to_dbl++) = *(from_dbl++);
}
You are performing an increment operation on the LValue (Left side value of the assignment operator). Logically and by definition, a LValue must always be a variable. It cannot be a constant. When you are performing an increment operation, it is leaving a constant value on the Left Side which is giving you the error.
First before answering let me just say: Don't try to out-micro-optimize your compiler/library. The compiler writers will win something like 99 times out of 100. Use std::copy or memcpy depending on the types you're copying and needs.
Other answers have noted that you can solve the immediate compilation errors with temporary variables.
I don't recommend this under any circumstances do the following, but I believe you can also accomplish this by casting to a reference type:
void FrMemCopy(void *to, const void *from, size_t sz)
{
size_t sz8 = sz >> 3;
size_t sz1 = sz - (sz8 << 3);
while (sz8-- != 0) {
*((double *&)to)++ = *((double *&)from)++;
}
while (sz1-- != 0) {
*((char *&)to)++ = *((char *&)from)++;
}
}