मुझे पता है कि यह एक बहुत ही सामान्य विषय है, लेकिन जितना विशिष्ट यूबी को ढूंढना आसान है, मुझे अब तक यह संस्करण नहीं मिला।
इसलिए, मैं डेटा की वास्तविक प्रतिलिपि से बचने के दौरान पिक्सेल वस्तुओं को औपचारिक रूप से पेश करने की कोशिश कर रहा हूं।
क्या यह मान्य है?
struct Pixel {
uint8_t red;
uint8_t green;
uint8_t blue;
uint8_t alpha;
};
static_assert(std::is_trivial_v<Pixel>);
Pixel* promote(std::byte* data, std::size_t count)
{
Pixel * const result = reinterpret_cast<Pixel*>(data);
while (count-- > 0) {
new (data) Pixel{
std::to_integer<uint8_t>(data[0]),
std::to_integer<uint8_t>(data[1]),
std::to_integer<uint8_t>(data[2]),
std::to_integer<uint8_t>(data[3])
};
data += sizeof(Pixel);
}
return result; // throw in a std::launder? I believe it is not mandatory here.
}
अपेक्षित उपयोग पैटर्न, भारी सरलीकृत:
std::byte * buffer = getSomeImageData();
auto pixels = promote(buffer, 800*600);
// manipulate pixel data
अधिक विशेष रूप से:
- क्या इस कोड में अच्छी तरह से परिभाषित व्यवहार है?
- यदि हाँ, तो क्या यह लौटे हुए पॉइंटर का उपयोग करने के लिए सुरक्षित है?
- यदि हाँ, तो इसे और किस
Pixel
प्रकार से बढ़ाया जा सकता है? (is_trivial प्रतिबंध को आराम? केवल 3 घटकों के साथ पिक्सेल?)।
क्लैंग और जीसीसी दोनों पूरे पाश को कुछ भी नहीं करने के लिए अनुकूलित करते हैं, जो कि मैं चाहता हूं। अब, मैं जानना चाहता हूं कि यह कुछ सी ++ नियमों का उल्लंघन करता है या नहीं।
यदि आप इसके साथ खेलना चाहते हैं तो Godbolt लिंक ।
(ध्यान दें: मैंने c ++ 17 के बावजूद टैग नहीं किया था std::byte
, क्योंकि प्रश्न का उपयोग करता है char
)
pixels[some_index]
या *(pixels + something)
? वह यूबी होगा।
Pixel
नए रखा अभी भीPixel
एस की एक सरणी नहीं है ।